diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg index a00e04d87086a3e0910487baf04a6c559e4391e5..eff5dcebbfb10b35d8ac727b77d2c306edf424b3 100644 --- a/libraries/dsp/st/hdllib.cfg +++ b/libraries/dsp/st/hdllib.cfg @@ -16,7 +16,6 @@ synth_files = src/vhdl/st_xst.vhd # src/vhdl/st_top.vhd src/vhdl/st_histogram.vhd - src/vhdl/st_histogram_reg.vhd src/vhdl/mms_st_histogram.vhd tb/vhdl/tb_st_pkg.vhd diff --git a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd index a17010950a6dd5c84c5cbece7105364dd6d51c08..9211e258055eea306ece595eb160b6f97f7f33df 100644 --- a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright 2020 +-- Copyright 2021 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- @@ -21,22 +21,11 @@ -- Author: -- . Daniel van der Schuur -- Purpose: --- . MMS-wrapper that adds registers and multi-instance support to st_histogram. +-- . MMS-wrapper that adds MM clock domain RAM readout and and multi-instance +-- support to st_histogram. -- Description: --- . st_histogram_reg implements the registers to control all g_nof_instances -- . This MMS wrapper contains logic to fill a local RAM with the contents of -- a selected st_histogram instance. --- Usage (see st_histogram_reg.vhd for the register map): --- . Reading RAM contents: --- 1) User writes instance to read (0..g_nof_instances-1) to ram_fill_inst --- register via reg_mosi --- 2) Users writes to bit 0 of fill_ram register via reg_mosi --- . ram_filling status will go high --- 3) User reads ram_filling status until it reads zero via reg_mosi --- 4) User reads freshly filled RAM contents via ram_mosi --- . Clearing the RAMs: --- . The inactive RAM is cleared automatically just before the next input sync. --- . ram_clearing status will go high during this time. LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; @@ -61,9 +50,6 @@ ENTITY mms_st_histogram IS mm_clk : IN STD_LOGIC; mm_rst : IN STD_LOGIC; - reg_mosi : IN t_mem_mosi; - reg_miso : OUT t_mem_miso; - ram_mosi : IN t_mem_mosi; ram_miso : OUT t_mem_miso ); @@ -73,7 +59,7 @@ ARCHITECTURE str OF mms_st_histogram IS CONSTANT c_reg_adr_w : NATURAL := 1; CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins); - CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync); + CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync)+1; CONSTANT c_ram : t_c_mem := (latency => 1, adr_w => c_ram_adr_w, @@ -83,16 +69,18 @@ ARCHITECTURE str OF mms_st_histogram IS CONSTANT c_addr_high : NATURAL := g_nof_bins-1; - SIGNAL common_ram_cr_cw_wr_mosi : t_mem_mosi; - SIGNAL nxt_common_ram_cr_cw_wr_mosi : t_mem_mosi; + SIGNAL common_ram_cr_cw_wr_mosi_arr : t_mem_mosi_arr(g_nof_instances-1 DOWNTO 0); + + SIGNAL common_ram_cr_cw_rd_mosi_arr : t_mem_mosi_arr(g_nof_instances-1 DOWNTO 0); + SIGNAL common_ram_cr_cw_rd_miso_arr : t_mem_miso_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL common_ram_cr_cw_rd_mosi : t_mem_mosi; - SIGNAL common_ram_cr_cw_rd_miso : t_mem_miso; + SIGNAL st_histogram_ram_mosi_arr : t_mem_mosi_arr(g_nof_instances-1 DOWNTO 0); + SIGNAL st_histogram_ram_miso_arr : t_mem_miso_arr(g_nof_instances-1 DOWNTO 0); SIGNAL ram_mosi_arr : t_mem_mosi_arr(g_nof_instances-1 DOWNTO 0); SIGNAL ram_miso_arr : t_mem_miso_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL ram_clearing_arr : STD_LOGIC_VECTOR(g_nof_instances-1 DOWNTO 0); + SIGNAL ram_fill_arr : STD_LOGIC_VECTOR(g_nof_instances-1 DOWNTO 0); SIGNAL ram_fill_inst : STD_LOGIC_VECTOR(ceil_log2(g_nof_instances)-1 DOWNTO 0); SIGNAL ram_fill_inst_int : NATURAL; @@ -106,7 +94,7 @@ ARCHITECTURE str OF mms_st_histogram IS BEGIN ------------------------------------------------------------------------------- - -- st_histogram instances and their registers + -- st_histogram instances ------------------------------------------------------------------------------- gen_st_histogram : FOR i IN 0 TO g_nof_instances-1 GENERATE u_st_histogram : ENTITY work.st_histogram @@ -121,113 +109,97 @@ BEGIN snk_in => snk_in_arr(i), - ram_clearing => ram_clearing_arr(i), - - ram_mosi => ram_mosi_arr(i), - ram_miso => ram_miso_arr(i) + ram_mosi => st_histogram_ram_mosi_arr(i), + ram_miso => st_histogram_ram_miso_arr(i) ); END GENERATE; - u_st_histogram_reg : ENTITY work.st_histogram_reg - GENERIC MAP ( - g_nof_instances => g_nof_instances - ) - PORT MAP ( - dp_clk => dp_clk, - dp_rst => dp_rst, - - ram_clearing => ram_clearing_arr(0), - ram_filling => ram_filling, - - mm_clk => mm_clk, - mm_rst => mm_rst, - - ram_fill_inst => ram_fill_inst, - ram_fill => ram_fill, - - reg_mosi => reg_mosi, - reg_miso => reg_miso - ); - - ------------------------------------------------------------------------------- -- Dual clock RAM: DP write side, MM read side + -- . How do we get the st_histogram RAM contents into the RAMs below? + -- . DPRAM -> read>write process -> MM RAM ------------------------------------------------------------------------------- - u_common_ram_cr_cw : ENTITY common_lib.common_ram_cr_cw - GENERIC MAP ( - g_technology => c_tech_select_default, - g_ram => c_ram, - g_init_file => "UNUSED" - ) - PORT MAP ( - wr_clk => dp_clk, - wr_rst => dp_rst, - wr_clken => '1', - wr_en => common_ram_cr_cw_wr_mosi.wr, - wr_adr => common_ram_cr_cw_wr_mosi.address(c_ram_adr_w-1 DOWNTO 0), - wr_dat => common_ram_cr_cw_wr_mosi.wrdata(c_ram_dat_w-1 DOWNTO 0), - rd_clk => mm_clk, - rd_rst => mm_rst, - rd_clken => '1', - rd_en => common_ram_cr_cw_rd_mosi.rd, - rd_adr => common_ram_cr_cw_rd_mosi.address(c_ram_adr_w-1 DOWNTO 0), - rd_dat => common_ram_cr_cw_rd_miso.rddata(c_ram_dat_w-1 DOWNTO 0), - rd_val => common_ram_cr_cw_rd_miso.rdval - ); + gen_common_ram_cr_cw : FOR i IN 0 TO g_nof_instances-1 GENERATE + u_common_ram_cr_cw : ENTITY common_lib.common_ram_cr_cw + GENERIC MAP ( + g_technology => c_tech_select_default, + g_ram => c_ram, + g_init_file => "UNUSED" + ) + PORT MAP ( + wr_clk => dp_clk, + wr_rst => dp_rst, + wr_clken => '1', + wr_en => common_ram_cr_cw_wr_mosi_arr(i).wr, + wr_adr => common_ram_cr_cw_wr_mosi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + wr_dat => common_ram_cr_cw_wr_mosi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0), + rd_clk => mm_clk, + rd_rst => mm_rst, + rd_clken => '1', + rd_en => common_ram_cr_cw_rd_mosi_arr(i).rd, + rd_adr => common_ram_cr_cw_rd_mosi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + rd_dat => common_ram_cr_cw_rd_miso_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0), + rd_val => common_ram_cr_cw_rd_miso_arr(i).rdval + ); + END GENERATE; -- User side MM bus for histogram readout - common_ram_cr_cw_rd_mosi <= ram_mosi; - ram_miso <= common_ram_cr_cw_rd_miso; + common_ram_cr_cw_rd_mosi_arr <= ram_mosi_arr; + ram_miso_arr <= common_ram_cr_cw_rd_miso_arr; ------------------------------------------------------------------------------- -- Logic to move st_histogram RAM contents into the dual clock RAM above ------------------------------------------------------------------------------- + -- Use only the status signal of st_histogram instance 0 + ram_fill <= snk_in_arr(0).sync; + -- Keep track of ram_filling status and address nxt_ram_filling <= '0' WHEN TO_UINT(address)=c_addr_high ELSE '1' WHEN ram_fill='1' ELSE ram_filling; nxt_address <= (OTHERS=>'0') WHEN ram_filling='0' ELSE INCR_UVEC(address, 1) WHEN ram_filling='1' ELSE address; - -- Help signal for bus selection - ram_fill_inst_int <= TO_UINT(ram_fill_inst); - -- Do read request on ram_mosi when ram_filling - p_mosi_arr: PROCESS (ram_filling, address, ram_fill_inst_int) - BEGIN - FOR i IN 0 TO g_nof_instances-1 LOOP - ram_mosi_arr(i) <= c_mem_mosi_rst; - IF i = ram_fill_inst_int THEN - ram_mosi_arr(i).rd <= ram_filling; - ram_mosi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= address; - END IF; - END LOOP; - END PROCESS; + gen_mosi_arr: FOR i IN 0 TO g_nof_instances-1 GENERATE + st_histogram_ram_mosi_arr(i).wr <= '0'; + st_histogram_ram_mosi_arr(i).wrdata <= (OTHERS=>'0'); + st_histogram_ram_mosi_arr(i).rd <= ram_filling; + st_histogram_ram_mosi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= address; + END GENERATE; -- Forward the read histogram data from ram_miso into write mosi of dual clock RAM - p_rd_miso_to_wr_mosi : PROCESS(ram_miso_arr, ram_fill_inst_int, address) - BEGIN - nxt_common_ram_cr_cw_wr_mosi <= common_ram_cr_cw_wr_mosi; - FOR i IN 0 TO g_nof_instances-1 LOOP - IF i = ram_fill_inst_int THEN - nxt_common_ram_cr_cw_wr_mosi.wr <= ram_miso_arr(i).rdval; - nxt_common_ram_cr_cw_wr_mosi.wrdata(c_ram_dat_w-1 DOWNTO 0) <= ram_miso_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0); - nxt_common_ram_cr_cw_wr_mosi.address(c_ram_adr_w-1 DOWNTO 0) <= address; - END IF; - END LOOP; - END PROCESS; + gen_rd_miso_to_wr_mosi: FOR i IN 0 TO g_nof_instances-1 GENERATE + common_ram_cr_cw_wr_mosi_arr(i).wr <= st_histogram_ram_miso_arr(i).rdval; + common_ram_cr_cw_wr_mosi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) <= st_histogram_ram_miso_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0); + common_ram_cr_cw_wr_mosi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= address; + END GENERATE; -- Registers p_clk : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN - common_ram_cr_cw_wr_mosi <= c_mem_mosi_rst; - address <= (OTHERS=>'0'); + address <= (OTHERS=>'0'); ram_filling <= '0'; ELSIF RISING_EDGE(dp_clk) THEN - common_ram_cr_cw_wr_mosi <= nxt_common_ram_cr_cw_wr_mosi; - address <= nxt_address; + address <= nxt_address; ram_filling <= nxt_ram_filling; END IF; END PROCESS; + ------------------------------------------------------------------------------- + -- MM multiplexing + ------------------------------------------------------------------------------- + u_common_mem_mux : ENTITY common_lib.common_mem_mux + GENERIC MAP ( + g_nof_mosi => g_nof_instances, + g_mult_addr_w => c_ram_adr_w + ) + PORT MAP ( + mosi => ram_mosi, + miso => ram_miso, + mosi_arr => ram_mosi_arr, + miso_arr => ram_miso_arr + ); + END str; + diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index f99a130b80b589f0a82b7120404d6c8267d09205..5e856c7f09b0c4cfd3517be04f164b6b4a4ae507 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- --- Copyright 2020 +-- Copyright 2021 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- @@ -20,7 +20,6 @@ -- Author: -- . Daniel van der Schuur --- . Jan Oudman -- Purpose: -- . Count incoming data values and keep the counts in RAM as a histogram -- Description: @@ -97,8 +96,6 @@ ENTITY st_histogram IS snk_in : IN t_dp_sosi; -- Active RAM page swaps on snk_in.sync - ram_clearing : OUT STD_LOGIC; -- Status output: high while RAM is being cleared - ram_mosi : IN t_mem_mosi; -- MM access to the inactive RAM page ram_miso : OUT t_mem_miso ); @@ -181,11 +178,11 @@ ARCHITECTURE rtl OF st_histogram IS SIGNAL nxt_data_cnt : STD_LOGIC_VECTOR(c_data_cnt_w-1 DOWNTO 0); SIGNAL ram_clear : STD_LOGIC; + SIGNAL ram_clearing : STD_LOGIC; SIGNAL ram_clear_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); SIGNAL nxt_ram_clear_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); - SIGNAL i_ram_clearing : STD_LOGIC; SIGNAL nxt_ram_clearing : STD_LOGIC; BEGIN @@ -383,12 +380,12 @@ BEGIN ram_clear <= '1' WHEN TO_UINT(data_cnt)=g_nof_data_per_sync-g_nof_bins-1 ELSE '0'; -- Signal to indicate when RAM is being cleared - nxt_ram_clearing <= '1' WHEN ram_clear='1' ELSE '0' WHEN TO_UINT(ram_clear_address)=g_nof_bins-1 ELSE i_ram_clearing; + nxt_ram_clearing <= '1' WHEN ram_clear='1' ELSE '0' WHEN TO_UINT(ram_clear_address)=g_nof_bins-1 ELSE ram_clearing; -- Address counter: 0 to g_nof_bins-1. - nxt_ram_clear_address <= INCR_UVEC(ram_clear_address, 1) WHEN i_ram_clearing='1' ELSE (OTHERS=>'0'); + nxt_ram_clear_address <= INCR_UVEC(ram_clear_address, 1) WHEN ram_clearing='1' ELSE (OTHERS=>'0'); - histogram_wr_mosi.wr <= i_ram_clearing; + histogram_wr_mosi.wr <= ram_clearing; histogram_wr_mosi.address(c_ram_adr_w-1 DOWNTO 0) <= ram_clear_address; histogram_wr_mosi.wrdata <= (OTHERS=>'0'); histogram_wr_mosi.rd <= '0'; @@ -398,16 +395,15 @@ BEGIN BEGIN IF dp_rst = '1' THEN ram_clear_address <= (OTHERS=>'0'); - i_ram_clearing <= '0'; + ram_clearing <= '0'; data_cnt <= (OTHERS=>'0'); ELSIF RISING_EDGE(dp_clk) THEN ram_clear_address <= nxt_ram_clear_address; - i_ram_clearing <= nxt_ram_clearing; + ram_clearing <= nxt_ram_clearing; data_cnt <= nxt_data_cnt; END IF; END PROCESS; - ram_clearing <= i_ram_clearing; ------------------------------------------------------------------------------- -- Expose the MM buses to the user diff --git a/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd index 0e8fea35b4f7ce3e88e4db243d208345db39ef2a..b805a7ae44ca43c0c249213e8da5453332e11e08 100644 --- a/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------- -- --- Copyright 2020 +-- Copyright 2021 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- @@ -23,14 +23,14 @@ -- Author: -- . Daniel van der Schuur -- Purpose: --- . +-- . Read and verify histogram RAM of instance 0 -- ModelSim usage: -- . (open project, compile) -- . (load simulation config) -- . as 8 -- . run -a -- Description: --- . +-- . This TB is self checking and stops after g_nof_sync test iterations. ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, mm_lib, dp_lib; @@ -49,7 +49,7 @@ ENTITY tb_mms_st_histogram IS g_nof_instances : NATURAL := 12; g_data_w : NATURAL := 14; g_nof_bins : NATURAL := 512; - g_nof_data_per_sync : NATURAL := 40000 + g_nof_data_per_sync : NATURAL := 32768 ); END tb_mms_st_histogram; @@ -83,9 +83,6 @@ ARCHITECTURE tb OF tb_mms_st_histogram IS ---------------------------------------------------------------------------- SIGNAL st_histogram_snk_in_arr : t_dp_sosi_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL st_histogram_reg_mosi : t_mem_mosi; - SIGNAL st_histogram_reg_miso : t_mem_miso; - SIGNAL st_histogram_ram_mosi : t_mem_mosi; SIGNAL st_histogram_ram_miso : t_mem_miso; @@ -163,9 +160,6 @@ BEGIN snk_in_arr => st_histogram_snk_in_arr, - reg_mosi => st_histogram_reg_mosi, - reg_miso => st_histogram_reg_miso, - ram_mosi => st_histogram_ram_mosi, ram_miso => st_histogram_ram_miso ); @@ -177,44 +171,23 @@ BEGIN p_ram_clear : PROCESS BEGIN st_histogram_ram_mosi <= c_mem_mosi_rst; - st_histogram_reg_mosi <= c_mem_mosi_rst; - ram_filling <= '0'; ram_rd_word <= (OTHERS=>'0'); + -- The first sync indicates start of incoming data - let it pass proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); proc_common_wait_some_cycles(mm_clk, 10); FOR i IN 0 TO g_nof_sync-2 LOOP -- Wiat for a full sync period of data proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); - -- The sync has passed, we can start reading the resulting histogram - FOR j IN 0 TO g_nof_instances-1 LOOP - -- Select st_histogram instance to read out - proc_mem_mm_bus_wr(1, j, mm_clk, st_histogram_reg_mosi); - proc_common_wait_some_cycles(mm_clk, 2); - - -- Enable RAM filling - proc_mem_mm_bus_wr(2, 1, mm_clk, st_histogram_reg_mosi); - proc_common_wait_some_cycles(mm_clk, 10); - - -- Wait until RAM filling is done - proc_mem_mm_bus_rd(2, mm_clk, st_histogram_reg_mosi); - ram_filling <= st_histogram_reg_miso.rddata(0); - proc_common_wait_some_cycles(mm_clk, 2); - WHILE ram_filling='1' LOOP - -- Read filling status - proc_mem_mm_bus_rd(2, mm_clk, st_histogram_reg_mosi); - ram_filling <= st_histogram_reg_miso.rddata(0); - proc_common_wait_some_cycles(mm_clk, 1); - END LOOP; - - -- Read out the RAM contents - FOR k IN 0 TO g_nof_bins-1 LOOP - proc_mem_mm_bus_rd(k, mm_clk, st_histogram_ram_mosi); - ram_rd_word <= st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0); - ram_rd_word_int <= TO_UINT(ram_rd_word); - END LOOP; - END LOOP; - END LOOP; + + -- Read out the RAM contents + FOR k IN 0 TO g_nof_bins-1 LOOP + proc_mem_mm_bus_rd(k, mm_clk, st_histogram_ram_mosi); + ram_rd_word <= st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0); + ram_rd_word_int <= TO_UINT(ram_rd_word); + END LOOP; + + END LOOP; END PROCESS; -- Register st_histogram_ram_miso.rdval so we read only valid data