Commit 5ecace74 authored by Jan Pospisil's avatar Jan Pospisil

added RegSyncer entity for CDC of vectors

parent 2ec6d762
library ieee;
use ieee.std_logic_1164.all;
entity delay is
entity Delay is
generic (
g_Width: integer := 1;
g_Delay: integer := 5;
......
library ieee;
use ieee.std_logic_1164.all;
entity EdgeDetector is
port (
Clk_ik: in std_logic;
Signal_i: in std_logic;
Edge_o: out std_logic
);
end entity;
architecture rising of EdgeDetector is
signal History: std_logic := '0';
begin
pDelay: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
History <= Signal_i;
end if;
end process;
Edge_o <= Signal_i and not History;
end architecture;
architecture falling of EdgeDetector is
signal History: std_logic := '0';
begin
pDelay: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
History <= Signal_i;
end if;
end process;
Edge_o <= not Signal_i and History;
end architecture;
\ No newline at end of file
--
-- Register with variable data length
-- Jan Pospisil
-- 2009; KP, FEL, CVUT
-- 2015; CTP, ALICE, CERN
-- 2016; BE-BI-QP, CERN
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Reg is
generic (
g_ResetValue: natural := 0
);
port (
Clk_ik: in std_logic;
Reset_ir: in std_logic;
Data_ib: in std_logic_vector;
Enable_i: in std_logic;
Data_ob: out std_logic_vector
);
end entity;
architecture syn of Reg is
constant c_ResetValue: std_logic_vector(Data_ib'range) := std_logic_vector(to_unsigned(g_ResetValue, Data_ib'length));
signal Data_b: std_logic_vector(Data_ib'range) := c_ResetValue;
begin
pReg: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
if Reset_ir = '1' then
Data_b <= c_ResetValue;
elsif Enable_i = '1' then
Data_b <= Data_ib;
end if;
end if;
end process;
Data_ob <= Data_b;
end architecture;
--
-- RegSyncer
-- Can be used for CDC for vectors with sparse load signals - i.e. where there are at least several
-- clock cycles between successive load signals (e.g. Wishbone registers)
--
library ieee;
use ieee.std_logic_1164.all;
entity RegSyncer is
port (
-- main signals
ClkIn_ik: in std_logic;
ClkOut_ik: in std_logic;
-- inputs
Data_ib: in std_logic_vector;
Load_i: in std_logic;
-- outputs
Data_ob: out std_logic_vector;
Load_o: out std_logic
);
end entity;
architecture syn of RegSyncer is
signal Data_qb, DataSynced_b: std_logic_vector(Data_ib'range);
signal NewData, NewDataSynced, NewDataSyncedPulse: std_logic := '0';
signal ResetNewDataFlag, ResetNewDataPulse: std_logic;
begin
-- data path
cRegIn: entity work.Reg(syn)
port map (
Clk_ik => ClkIn_ik,
Reset_ir => '0',
Data_ib => Data_ib,
Enable_i => Load_i,
Data_ob => Data_qb
);
cDataSyncer: entity work.Delay(syn)
generic map (
g_Width => Data_ib'length,
g_Delay => 3,
g_AsyncRegUsed => "TRUE"
)
port map (
Clk_ik => ClkOut_ik,
Data_ib => Data_qb,
Data_ob => DataSynced_b
);
cRegOut: entity work.Reg(syn)
port map (
Clk_ik => ClkOut_ik,
Reset_ir => '0',
Data_ib => DataSynced_b,
Enable_i => NewDataSyncedPulse,
Data_ob => Data_ob
);
-- control path
pRs: process (ClkIn_ik) is begin
if rising_edge(ClkIn_ik) then
if ResetNewDataPulse then
NewData <= '0';
elsif Load_i then
-- This load can be missed for processing if arrive to early, i.e. before
-- ResetNewDataPulse corresponding to the previous Load_i.
NewData <= '1';
end if;
end if;
end process;
cLoadSyncer: entity work.Delay(syn)
generic map (
g_Width => 1,
g_Delay => 4,
g_AsyncRegUsed => "TRUE"
)
port map (
Clk_ik => ClkOut_ik,
Data_ib(0) => NewData,
Data_ob(0) => NewDataSynced
);
cNewDataSyncedPulseGenerator: entity work.EdgeDetector(rising)
port map (
Clk_ik => ClkOut_ik,
Signal_i => NewDataSynced,
Edge_o => NewDataSyncedPulse
);
cLoadDelay: entity work.Delay(syn)
generic map (
g_Width => 1,
g_Delay => 2
)
port map (
Clk_ik => ClkOut_ik,
Data_ib(0) => NewDataSyncedPulse,
Data_ob(0) => Load_o
);
cResetNewDataSyncer: entity work.Delay(syn)
generic map (
g_Width => 1,
g_Delay => 3,
g_AsyncRegUsed => "TRUE"
)
port map (
Clk_ik => ClkIn_ik,
Data_ib(0) => NewDataSynced,
Data_ob(0) => ResetNewDataFlag
);
cResetNewDataPulseGenerator: entity work.EdgeDetector(rising)
port map (
Clk_ik => ClkIn_ik,
Signal_i => ResetNewDataFlag,
Edge_o => ResetNewDataPulse
);
end architecture;
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.RNG.all;
entity RegSyncer_tb is
end entity;
architecture testbench of RegSyncer_tb is
-- 2.prime periods
constant c_SlowClockPeriod: time := 106 ns;
constant c_QuickClockPeriod: time := 10 ns;
constant c_Width: positive := 8;
constant c_Loops: positive := 100; -- number of test for each clock configuration (S-Q, Q-S)
-- DUT signals
signal ClkIn_ik, ClkOut_ik: std_logic := '0';
signal Data_ib, Data_ob: std_logic_vector(c_Width-1 downto 0) := (others => 'X');
signal Load_i, Load_o: std_logic := '0';
-- TB signals
signal ClkSlow, ClkQuick: std_logic := '0';
signal SlowToQuick: std_logic := '0';
signal Result_b: std_logic_vector(Data_ob'range) := (others => 'X');
signal ResultReset: std_logic := '0';
procedure f_SlowTick(ticks: in natural) is begin
wait for ticks * c_SlowClockPeriod;
end procedure;
procedure f_QuiTick(ticks: in natural) is begin
wait for ticks * c_QuickClockPeriod;
end procedure;
procedure f_InputTick(ticks: in natural) is begin
if SlowToQuick then
f_SlowTick(ticks);
else
f_QuiTick(ticks);
end if;
end procedure;
procedure f_OutTick(ticks: in natural) is begin
if SlowToQuick then
f_QuiTick(ticks);
else
f_SlowTick(ticks);
end if;
end procedure;
begin
cDUT: entity work.RegSyncer(syn)
port map (
ClkIn_ik => ClkIn_ik,
ClkOut_ik => ClkOut_ik,
Data_ib => Data_ib,
Load_i => Load_i,
Data_ob => Data_ob,
Load_o => Load_o
);
pSlowGenerator: process is begin
wait for c_SlowClockPeriod/2;
ClkSlow <= not ClkSlow;
end process;
pQuickGenerator: process is begin
wait for c_QuickClockPeriod/2;
ClkQuick <= not ClkQuick;
end process;
ClkIn_ik <=
ClkSlow when SlowToQuick else
ClkQuick;
ClkOut_ik <=
ClkQuick when SlowToQuick else
ClkSlow;
pResultReg: process (ClkOut_ik) is begin
if rising_edge(ClkOut_ik) then
if ResultReset then
Result_b <= (others => 'X');
elsif Load_o then
Result_b <= Data_ob;
end if;
end if;
end process;
pTest: process is
variable Data_b: std_logic_vector(Data_ib'range) := (others => '0');
variable Unf: Uniform := InitUniform(7, 0.0, (2.0**c_Width)-1.0);
procedure f_RandomizeData is begin
GenRnd(Unf);
Data_b := std_logic_vector(to_unsigned(integer(Unf.rnd), c_Width));
end procedure;
procedure f_WriteData is begin
-- reset result register
ResultReset <= '1';
f_OutTick(1);
ResultReset <= '0';
f_OutTick(1);
-- write data
Data_ib <= Data_b;
Load_i <= '1';
f_InputTick(1);
Data_ib <= (others => 'X');
Load_i <= '0';
end procedure;
procedure f_CheckData is begin
assert Result_b = Data_b
report "Data mismatch!"
severity failure;
end procedure;
begin
for i in 0 to 1 loop
for j in 1 to c_Loops loop
f_RandomizeData;
f_InputTick(10);
f_WriteData;
f_OutTick(10);
f_CheckData;
end loop;
SlowToQuick <= not SlowToQuick;
f_SlowTick(10);
end loop;
assert false report "NONE. End of simulation." severity failure;
wait;
end process;
end architecture;
\ No newline at end of file
This diff is collapsed.
......@@ -11,19 +11,24 @@ vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_fi
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/common/gc_serial_dac.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FfpgPkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/WbSlaveWrapper.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DacsController.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/pulseGenerator.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/pulseGeneratorTime.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DelayController.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/Counter.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/CounterLength.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ShiftRegister.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ResetSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/Delay.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/EdgeDetector.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/Reg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/RegSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FfpgPkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/WbSlaveWrapper.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DelayController.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DacsController.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DelayedPulseGenerator/Fsm.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DelayedPulseGenerator/RfClkDomain.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/DelayedPulseGenerator/DelayedPulseGenerator.vhd
......
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