Commit fa9ea901 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

softpll-ng: initial commit

parents
files = ["spll_period_detect.vhd",
"spll_wbgen2_pkg.vhd",
# "wr_softpll_ng.vhd",
# "xwr_softpll_ng.vhd",
"spll_wb_slave.vhd"]
\ No newline at end of file
#!/bin/bash
wbgen2 -C softpll_regs.h -V spll_wb_slave.vhd -K ../../sim/softpll_regs_ng.vh -C softpll_regs.h --hstyle record -p spll_wbgen2_pkg.vhd spll_wb_slave.wb
\ No newline at end of file
-------------------------------------------------------------------------------
-- Title : SoftPLL - linear frequency/period detector.
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : softpll_period_detect.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2012-01-17
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Simple linear frequency detector with programmable error
-- setpoint and gating period. The measured clocks are: clk_ref_i and clk_fbck_i.
-- The error value is outputted every 2^(hpll_fbcr_fd_gate_i + 14) cycles on a
-- freq_err_o. A pulse is produced on freq_err_stb_p_o every time freq_err_o
-- is updated with a new value. freq_err_o value is:
-- - positive when clk_fbck_i is slower than selected frequency setpoint
-- - negative when clk_fbck_i is faster than selected frequency setpoint
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity spll_period_detect is
generic(
g_num_ref_inputs : integer := 6);
port (
-------------------------------------------------------------------------------
-- Clocks & resets
-------------------------------------------------------------------------------
-- reference clocks
clk_ref_i : in std_logic_vector(g_num_ref_inputs-1 downto 0);
-- fed-back (VCO) clock
clk_dmtd_i : in std_logic;
-- system clock (wishbone and I/O)
clk_sys_i : in std_logic;
-- reset signals (the same reset synced to different clocks)
rst_n_dmtdclk_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Outputs
-------------------------------------------------------------------------------
-- frequency error value (signed)
freq_err_o : out std_logic_vector(11 downto 0);
-- frequency error valid pulse
freq_err_stb_p_o : out std_logic;
in_sel_i : in std_logic_vector(4 downto 0)
);
end spll_period_detect;
architecture rtl of spll_period_detect is
constant c_COUNTER_BITS : integer := 19;
constant c_GATING_PERIOD : integer := 1024;
-- frequency counters: feedback clock & gating counter
signal in_muxed : std_logic;
signal in_sel_onehot : std_logic_vector(g_num_ref_inputs-1 downto 0);
signal freq : std_logic_vector(19 downto 0);
signal freq_valid_dmtdclk, freq_valid_sysclk : std_logic;
signal freq_valid_dmtdclk_d0, freq_valid_dmtdclk_pulse : std_logic;
begin -- rtl
gen_in_sel_mask : for i in 0 to g_num_ref_inputs-1 generate
in_sel_onehot(i) <= '1' when i = to_integer(unsigned(in_sel_i)) else '0';
end generate gen_in_sel_mask; -- i
in_muxed <= '1' when unsigned(in_sel_onehot and clk_ref_i) /= 0 else '0';
U_Freq_Meter : gc_frequency_meter
generic map (
g_with_internal_timebase => true,
g_clk_sys_freq => c_GATING_PERIOD,
g_counter_bits => 20)
port map (
clk_sys_i => clk_dmtd_i,
clk_in_i => in_muxed,
rst_n_i => rst_n_dmtdclk_i,
pps_p1_i => '0',
freq_o => freq,
freq_valid_o => freq_valid_dmtdclk);
U_Pulse_Sync : gc_pulse_synchronizer
port map (
clk_in_i => clk_dmtd_i,
clk_out_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
d_p_i => freq_valid_dmtdclk_pulse,
q_p_o => freq_valid_sysclk);
p_edge_detect: process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
freq_valid_dmtdclk_d0 <= freq_valid_dmtdclk;
end if;
end process;
freq_valid_dmtdclk_pulse <= freq_valid_dmtdclk and not freq_valid_dmtdclk_d0;
p_output : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
freq_err_o <= (others => '0');
freq_err_stb_p_o <= '0';
elsif(freq_valid_sysclk = '1') then
freq_err_o <= std_logic_vector(resize(unsigned(freq) - c_GATING_PERIOD, freq_err_o'length));
freq_err_stb_p_o <= '1';
else
freq_err_stb_p_o <= '0';
end if;
end if;
end process;
end rtl;
This diff is collapsed.
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "WR Softcore PLL";
hdl_entity = "spll_wb_slave";
prefix = "SPLL";
reg {
name = "SPLL Control/Status Register";
prefix = "CSR";
field {
align = 8;
name = "Period detector reference select";
prefix = "PER_SEL";
size = 6;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
align = 8;
name = "Number of reference channels (max: 32)";
prefix = "N_REF";
type = SLV;
size = 6;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
align = 8;
name = "Number of output channels (max: 8)";
prefix = "N_OUT";
type = SLV;
size = 3;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Output Channel Control Register";
prefix = "OCCR";
field {
align = 8;
name = "Output Channel HW enable flag";
prefix = "OUT_EN";
type = SLV;
size = 8;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Output Channel locked flag";
prefix = "OUT_LOCK";
type = SLV;
size = 8;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Reference Channel Enable Register";
prefix = "RCER";
field {
name = "Reference Channel Enable";
description = "write 1: enables tag generation on the input channel corresponding to the written bit\
write 0: disables tag generation";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
reg {
name = "Output Channel Enable Register";
prefix = "OCER";
field {
name = "Output Channel Enable";
description = "write 1: enables tag generation on the output channel corresponding to the written bit\
write 0: disables tag generation";
type = SLV;
size = 8;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
reg {
name = "HPLL Period Error";
prefix = "PER_HPLL";
field {
name = "Period error value";
prefix = "ERROR";
type = SLV;
size = 16;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
ack_read = "tag_hpll_rd_period_o";
};
field {
name = "Period Error Valid";
prefix = "VALID";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Helper DAC Output";
prefix = "DAC_HPLL";
field {
name = "DAC value";
type = PASS_THROUGH;
size = 16;
};
};
reg {
name = "Main DAC Output";
prefix = "DAC_MAIN";
field {
name = "DAC value";
prefix = "VALUE";
type = PASS_THROUGH;
size = 16;
};
field {
name = "DAC select";
prefix = "DAC_SEL";
description = "Selects the output DAC to be updated with VALUE";
type = PASS_THROUGH;
size = 4;
};
};
reg {
name = "Deglitcher threshold";
prefix = "DEGLITCH_THR";
field {
name = "Threshold";
type = SLV;
size = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
fifo_reg {
name = "Tag Readout Register";
prefix = "TRR";
direction = CORE_TO_BUS;
size = 32;
flags_dev = {FIFO_FULL};
flags_bus = {FIFO_EMPTY};
field {
name = "Tag value";
prefix = "VALUE";
type = SLV;
size = 24;
};
field {
name = "Channel ID";
description = "Tagged Channel ID: 0-31: reference tags, 32-47: output tags";
prefix = "CHAN_ID";
type = SLV;
size = 7;
};
field {
name = "Discontinuous bit";
prefix = "DISC";
description = "1: previous tag has been dropped due to FIFO overflow";
type = BIT;
};
};
irq {
name = "Got a tag";
prefix = "TAG";
trigger = LEVEL_1;
};
};
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for WR Softcore PLL
---------------------------------------------------------------------------------------
-- File : spll_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from wr_softpll.wb
-- Created : Wed Jan 18 13:13:08 2012
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_softpll.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wbgen2_pkg.all;
package SPLL_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_SPLL_in_registers is record
spll_csr_n_ref_i : std_logic_vector(5 downto 0);
spll_csr_n_out_i : std_logic_vector(2 downto 0);
spll_occr_out_en_i : std_logic_vector(7 downto 0);
spll_rcer_i : std_logic_vector(31 downto 0);
spll_ocer_i : std_logic_vector(7 downto 0);
spll_per_hpll_error_i : std_logic_vector(15 downto 0);
spll_per_hpll_valid_i : std_logic;
spll_trr_wr_req_i : std_logic;
spll_trr_value_i : std_logic_vector(23 downto 0);
spll_trr_chan_id_i : std_logic_vector(6 downto 0);
spll_trr_disc_i : std_logic;
end record;
constant c_SPLL_in_registers_init_value: t_SPLL_in_registers := (
spll_csr_n_ref_i => (others => '0'),
spll_csr_n_out_i => (others => '0'),
spll_occr_out_en_i => (others => '0'),
spll_rcer_i => (others => '0'),
spll_ocer_i => (others => '0'),
spll_per_hpll_error_i => (others => '0'),
spll_per_hpll_valid_i => '0',
spll_trr_wr_req_i => '0',
spll_trr_value_i => (others => '0'),
spll_trr_chan_id_i => (others => '0'),
spll_trr_disc_i => '0'
);
-- Output registers (WB slave -> user design)
type t_SPLL_out_registers is record
spll_csr_per_sel_o : std_logic_vector(5 downto 0);
spll_occr_out_lock_o : std_logic_vector(7 downto 0);
spll_rcer_o : std_logic_vector(31 downto 0);
spll_rcer_load_o : std_logic;
spll_ocer_o : std_logic_vector(7 downto 0);
spll_ocer_load_o : std_logic;
spll_dac_hpll_o : std_logic_vector(15 downto 0);
spll_dac_hpll_wr_o : std_logic;
spll_dac_main_value_o : std_logic_vector(15 downto 0);
spll_dac_main_value_wr_o : std_logic;
spll_dac_main_dac_sel_o : std_logic_vector(3 downto 0);
spll_dac_main_dac_sel_wr_o : std_logic;
spll_deglitch_thr_o : std_logic_vector(15 downto 0);
spll_trr_wr_full_o : std_logic;
end record;
constant c_SPLL_out_registers_init_value: t_SPLL_out_registers := (
spll_csr_per_sel_o => (others => '0'),
spll_occr_out_lock_o => (others => '0'),
spll_rcer_o => (others => '0'),
spll_rcer_load_o => '0',
spll_ocer_o => (others => '0'),
spll_ocer_load_o => '0',
spll_dac_hpll_o => (others => '0'),
spll_dac_hpll_wr_o => '0',
spll_dac_main_value_o => (others => '0'),
spll_dac_main_value_wr_o => '0',
spll_dac_main_dac_sel_o => (others => '0'),
spll_dac_main_dac_sel_wr_o => '0',
spll_deglitch_thr_o => (others => '0'),
spll_trr_wr_full_o => '0'
);
function "or" (left, right: t_SPLL_in_registers) return t_SPLL_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
end package;
package body SPLL_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if(x = 'X' or x = 'U') then
return '0';
else
return x;
end if;
end function;
function "or" (left, right: t_SPLL_in_registers) return t_SPLL_in_registers is
variable tmp: t_SPLL_in_registers;
begin
tmp.spll_csr_n_ref_i := left.spll_csr_n_ref_i or right.spll_csr_n_ref_i;
tmp.spll_csr_n_out_i := left.spll_csr_n_out_i or right.spll_csr_n_out_i;
tmp.spll_occr_out_en_i := left.spll_occr_out_en_i or right.spll_occr_out_en_i;
tmp.spll_rcer_i := left.spll_rcer_i or right.spll_rcer_i;
tmp.spll_ocer_i := left.spll_ocer_i or right.spll_ocer_i;
tmp.spll_per_hpll_error_i := left.spll_per_hpll_error_i or right.spll_per_hpll_error_i;
tmp.spll_per_hpll_valid_i := left.spll_per_hpll_valid_i or right.spll_per_hpll_valid_i;
tmp.spll_trr_wr_req_i := left.spll_trr_wr_req_i or right.spll_trr_wr_req_i;
tmp.spll_trr_value_i := left.spll_trr_value_i or right.spll_trr_value_i;
tmp.spll_trr_chan_id_i := left.spll_trr_chan_id_i or right.spll_trr_chan_id_i;
tmp.spll_trr_disc_i := left.spll_trr_disc_i or right.spll_trr_disc_i;
return tmp;
end function;
end package body;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment