diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd index 1b4d1753f9c49ad38b28390d1df7906969393848..94347aaca1aeccb0c0ed9efed5a10b24fbc668e3 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd @@ -61,7 +61,6 @@ ENTITY sdp_crosslets_subband_select IS reg_bsn_sync_scheduler_xsub_miso : OUT t_mem_miso := c_mem_miso_rst; out_crosslets_info : OUT STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) - ); END sdp_crosslets_subband_select; @@ -105,6 +104,7 @@ ARCHITECTURE str OF sdp_crosslets_subband_select IS SIGNAL crosslets_info_reg : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL crosslets_info_reg_in : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); SIGNAL active_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL i_out_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); BEGIN --------------------------------------------------------------- @@ -152,9 +152,11 @@ BEGIN in_reg => crosslets_info_reg_in, out_reg => crosslets_info_reg ); - p_set_unused_crosslets : PROCESS(crosslets_info_reg) + + p_set_unused_crosslets : PROCESS(i_out_crosslets_info) BEGIN - crosslets_info_reg_in <= crosslets_info_reg; -- Always use crosslets info 6:0 + step(@ index 15) + -- MM readback the currently active crosslets info, instead of the initial MM written crosslets_info_reg + crosslets_info_reg_in <= i_out_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15) -- Set crosslets 14:7 to -1 FOR I IN g_N_crosslets TO c_sdp_mm_reg_crosslets_info.nof_dat - 2 LOOP crosslets_info_reg_in((I+1) * c_sdp_crosslets_index_w - 1 DOWNTO I * c_sdp_crosslets_index_w ) <= TO_SVEC(-1, c_sdp_crosslets_index_w); @@ -309,6 +311,7 @@ BEGIN gen_crosslets_info : FOR I IN 0 TO g_N_crosslets-1 GENERATE active_crosslets_info((I+1)*c_sdp_crosslets_index_w-1 DOWNTO I*c_sdp_crosslets_index_w) <= TO_UVEC(r.offsets(I), c_sdp_crosslets_index_w); END GENERATE; + -- pipeline for alignment with sync u_common_pipeline : ENTITY common_lib.common_pipeline GENERIC MAP( @@ -321,9 +324,11 @@ BEGIN clk => dp_clk, in_en => row_sosi.sync, in_dat => active_crosslets_info, - out_dat => out_crosslets_info + out_dat => i_out_crosslets_info ); + out_crosslets_info <= i_out_crosslets_info; + --------------------------------------------------------------- -- Out sosi pipeline --------------------------------------------------------------- diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd index 2b6912dc420207a7adb5bd133be40546074c798c..d58cd1b58e1de6fbc64612736e5f3bad2ce48e72 100644 --- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd +++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd @@ -55,28 +55,31 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS CONSTANT c_rl : NATURAL := 1; CONSTANT c_nof_sync : NATURAL := 5; CONSTANT c_nof_block_per_sync : NATURAL := 4; - CONSTANT c_nof_ch_in : NATURAL := 1024; -- nof input words per block, identical for all input streams. CONSTANT c_dsp_data_w : NATURAL := c_sdp_W_subband; - CONSTANT c_nof_ch_sel_row : NATURAL := c_sdp_P_pfb; CONSTANT c_N_crosslets : NATURAL := 2; - CONSTANT c_ch_sel_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); - CONSTANT c_nof_ch_sel_col : NATURAL := c_sdp_Q_fft; -- nof of sequential collums to select per row. - CONSTANT c_ch_sel_step : NATURAL := 3; -- offset step size to increase per sync interval + CONSTANT c_crosslet_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); + CONSTANT c_crosslet_step : NATURAL := 3; -- offset step size to increase per sync interval + CONSTANT c_nof_ch_in : NATURAL := 1024; -- nof input words per block, identical for all input streams. + CONSTANT c_nof_ch_sel_row : NATURAL := c_sdp_P_pfb; + CONSTANT c_nof_ch_sel_col : NATURAL := c_sdp_Q_fft; -- nof of sequential columns to select per row. CONSTANT c_nof_ch_sel : NATURAL := c_N_crosslets*c_nof_ch_sel_col*c_nof_ch_sel_row; + CONSTANT c_ctrl_interval_size : NATURAL := c_nof_block_per_sync * c_nof_ch_in; CONSTANT c_scheduled_bsn : NATURAL := 11; CONSTANT c_nof_block_dly : NATURAL := c_nof_block_per_sync; + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL mm_clk : STD_LOGIC := '1'; - SIGNAL tb_end : STD_LOGIC; - - SIGNAL mm_mosi : t_mem_mosi; - SIGNAL mm_miso : t_mem_miso; - + + SIGNAL mm_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL mm_miso : t_mem_miso; + SIGNAL rd_crosslet_offsets : t_natural_arr(0 TO c_N_crosslets-1) := (0, 15); + SIGNAL rd_crosslet_step : NATURAL; + SIGNAL mm_trigger_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL mm_trigger_miso : t_mem_miso; @@ -91,32 +94,74 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS SIGNAL out_sosi : t_dp_sosi; - SIGNAL exp_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL out_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL exp_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL out_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL exp_crosslets_info_rec : t_sdp_crosslets_info; + SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info; + BEGIN clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; rst <= '1', '0' AFTER c_clk_period*7; - p_select_stimuli : PROCESS + p_mm_stimuli : PROCESS VARIABLE k : NATURAL; BEGIN - proc_common_wait_until_low(mm_clk, rst); proc_common_wait_some_cycles(mm_clk, 50); -- Give dut some time to start - -- BSN Scheduler + + -- Set BSN sync scheduler proc_mem_mm_bus_wr(1, c_ctrl_interval_size, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(2, c_scheduled_bsn, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(3, 0, mm_clk, mm_trigger_miso, mm_trigger_mosi); proc_mem_mm_bus_wr(0, 1, mm_clk, mm_trigger_miso, mm_trigger_mosi); --enable + -- Set crosslet info + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_wr(I, c_crosslet_offsets(I), mm_clk, mm_miso, mm_mosi); --offsets + END LOOP; + proc_mem_mm_bus_wr(15, c_crosslet_step, mm_clk, mm_miso, mm_mosi); --step + proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period); - -- crosslet info + -- Verify that MM reads the active crosslets_info + -- a) Readback crosslet info after rst release + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_rd(I, mm_clk, mm_miso, mm_mosi); --offsets + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_offsets(I) <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + END LOOP; + proc_mem_mm_bus_rd(15, mm_clk, mm_miso, mm_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_step <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + -- Verify that readback crosslet info is active crosslets_info FOR I IN 0 TO c_N_crosslets-1 LOOP - proc_mem_mm_bus_wr(I, c_ch_sel_offsets(I), mm_clk, mm_miso, mm_mosi); --offsets + ASSERT rd_crosslet_offsets(I) = 0 REPORT "Wrong crosslet offset after rst." SEVERITY ERROR; END LOOP; - proc_mem_mm_bus_wr(15, c_ch_sel_step, mm_clk, mm_miso, mm_mosi); --step + ASSERT rd_crosslet_step = 0 REPORT "Wrong crosslet step after rst." SEVERITY ERROR; + + -- b) Read crosslet_info in every sync interval + WHILE TRUE LOOP + proc_common_wait_until_hi_lo(clk, out_sosi.sync); + proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period); + -- Readback crosslet info + FOR I IN 0 TO c_N_crosslets-1 LOOP + proc_mem_mm_bus_rd(I, mm_clk, mm_miso, mm_mosi); --offsets + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_offsets(I) <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + END LOOP; + proc_mem_mm_bus_rd(15, mm_clk, mm_miso, mm_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + rd_crosslet_step <= TO_UINT(mm_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + -- Verify that readback crosslet info is active crosslets_info + FOR I IN 0 TO c_N_crosslets-1 LOOP + ASSERT rd_crosslet_offsets(I) = exp_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR; + END LOOP; + ASSERT rd_crosslet_step = exp_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR; + END LOOP; + WAIT; END PROCESS; @@ -179,16 +224,16 @@ BEGIN exp_sosi <= c_dp_sosi_rst; WAIT UNTIL rising_edge(out_sosi.sop); - exp_crosslets_info(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_ch_sel_step, c_sdp_crosslets_index_w); + exp_crosslets_info_slv(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_step, c_sdp_crosslets_index_w); FOR C IN 0 TO c_nof_ch_sel_col-1 LOOP - exp_crosslets_info((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_ch_sel_offsets(C) + v_sync_ix * c_ch_sel_step, c_sdp_crosslets_index_w); + exp_crosslets_info_slv((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step, c_sdp_crosslets_index_w); END LOOP; FOR J IN 0 TO c_nof_ch_sel-1 LOOP v_offset := J / (c_nof_ch_sel_col*c_nof_ch_sel_row); v_col := J MOD c_nof_ch_sel_col; v_row := (J/c_nof_ch_sel_col) MOD c_nof_ch_sel_row; - v_k := c_nof_ch_sel_col * v_sync_ix * c_ch_sel_step; + v_k := c_nof_ch_sel_col * v_sync_ix * c_crosslet_step; exp_sosi <= c_dp_sosi_rst; exp_sosi.valid <= '1'; @@ -202,8 +247,8 @@ BEGIN exp_sosi.eop <= '1'; END IF; - exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA( (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_ch_sel_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); - exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_ch_sel_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); + exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA( (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); + exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0)); proc_common_wait_some_cycles(clk, 1); END LOOP; @@ -219,7 +264,7 @@ BEGIN ASSERT out_sosi.sop = exp_sosi.sop REPORT "Wrong out_sosi.sop" SEVERITY ERROR; ASSERT out_sosi.eop = exp_sosi.eop REPORT "Wrong out_sosi.eop" SEVERITY ERROR; ASSERT out_sosi.sync = exp_sosi.sync REPORT "Wrong out_sosi.sync" SEVERITY ERROR; - ASSERT out_crosslets_info = exp_crosslets_info REPORT "Wrong out_crosslets_info" SEVERITY ERROR; + ASSERT out_crosslets_info_slv = exp_crosslets_info_slv REPORT "Wrong out_crosslets_info_slv" SEVERITY ERROR; IF exp_sosi.valid = '1' THEN ASSERT out_sosi.re = exp_sosi.re REPORT "Wrong out_sosi.re" SEVERITY ERROR; ASSERT out_sosi.im = exp_sosi.im REPORT "Wrong out_sosi.im" SEVERITY ERROR; @@ -249,7 +294,11 @@ BEGIN in_sosi_arr => in_sosi_arr, out_sosi => out_sosi, - out_crosslets_info => out_crosslets_info + out_crosslets_info => out_crosslets_info_slv ); + -- Map crosslets_info slv to record for easier view in Wave window + exp_crosslets_info_rec <= func_sdp_map_crosslets_info(exp_crosslets_info_slv); + out_crosslets_info_rec <= func_sdp_map_crosslets_info(out_crosslets_info_slv); + END tb; diff --git a/libraries/base/diag/src/vhdl/diag_wg.vhd b/libraries/base/diag/src/vhdl/diag_wg.vhd index 53ab3a2a5daf43706991a4e810991280920e5dc8..a30ec8a8608aa3fce0021d2829869ddaf3116558 100644 --- a/libraries/base/diag/src/vhdl/diag_wg.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg.vhd @@ -21,7 +21,12 @@ -- Purpose: Sine waveform generator -- Description: --- . Based on diag_waveproc from LOFAR. +-- . Based on diag_waveproc from LOFAR1. +-- . Monitor the active WG ctrl: +-- - WG ctrl.mode = off takes effect immediately +-- - WG ctrl.ampl takes effect immediately +-- - Changing WG ctrl.phase and ctrl.freq require a restart to take effect, +-- to have synchronous phase relation between different WG. -- Remarks: -- . For WG sine periods that integer fit in the WG buffer size the carrier -- wWave (CW) frequency is exact. For fractional WG frequencies, for which @@ -73,6 +78,7 @@ ENTITY diag_wg IS buf_rdval : IN STD_LOGIC; ctrl : IN t_diag_wg; + mon_ctrl : OUT t_diag_wg; out_ovr : OUT STD_LOGIC; out_dat : OUT STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); @@ -117,8 +123,11 @@ ARCHITECTURE rtl OF diag_wg IS SIGNAL state : state_enum; SIGNAL nxt_state : state_enum; + SIGNAL prev_state : state_enum; SIGNAL idle : STD_LOGIC; + SIGNAL i_mon_ctrl : t_diag_wg; + SIGNAL nxt_mon_ctrl : t_diag_wg; SIGNAL nof_samples : STD_LOGIC_VECTOR(g_buf_addr_w DOWNTO 0); -- only use effective range of nof_samples+1 SIGNAL nxt_nof_samples : STD_LOGIC_VECTOR(g_buf_addr_w DOWNTO 0); SIGNAL sample_cnt : NATURAL RANGE 0 TO 2**g_buf_addr_w-1; @@ -126,7 +135,7 @@ ARCHITECTURE rtl OF diag_wg IS SIGNAL sample_step : NATURAL RANGE 0 TO g_rate_factor; SIGNAL nxt_sample_step : NATURAL; SIGNAL init_repeat_done : STD_LOGIC; - + SIGNAL phase : STD_LOGIC_VECTOR(ctrl.freq'LENGTH-1 DOWNTO 0); SIGNAL nxt_phase : STD_LOGIC_VECTOR(phase'RANGE); SIGNAL phase_step : STD_LOGIC_VECTOR(phase'RANGE); @@ -159,12 +168,15 @@ ARCHITECTURE rtl OF diag_wg IS BEGIN + mon_ctrl <= i_mon_ctrl; + registers : PROCESS(clk, rst) BEGIN IF rst = '1' THEN -- Internal registers. nof_samples <= (OTHERS => '0'); state <= s_off; + prev_state <= s_off; sample_cnt <= 0; sample_step <= 0; phase <= (OTHERS => '0'); @@ -172,6 +184,7 @@ BEGIN init_phase_cnt <= 0; init_sync <= '0'; -- Output registers. + i_mon_ctrl <= c_diag_wg_rst; buf_addr <= (OTHERS => '0'); buf_rden <= '0'; out_ovr <= '0'; @@ -182,6 +195,7 @@ BEGIN -- Internal registers. nof_samples <= nxt_nof_samples; state <= nxt_state; + prev_state <= state; sample_cnt <= nxt_sample_cnt; sample_step <= nxt_sample_step; phase <= nxt_phase; @@ -189,6 +203,7 @@ BEGIN init_phase_cnt <= nxt_init_phase_cnt; init_sync <= nxt_init_sync; -- Output registers. + i_mon_ctrl <= nxt_mon_ctrl; buf_addr <= nxt_buf_addr; buf_rden <= nxt_buf_rden; out_ovr <= nxt_out_ovr; @@ -317,9 +332,23 @@ BEGIN END IF; END PROCESS; - ctrl_ampl <= '0' & ctrl.ampl; + p_mon_ctrl : PROCESS(i_mon_ctrl, ctrl, prev_state, state) + BEGIN + nxt_mon_ctrl <= i_mon_ctrl; + IF TO_UINT(ctrl.mode) = c_diag_wg_mode_off THEN + -- WG immediately goes into off state + nxt_mon_ctrl <= ctrl; + ELSIF prev_state = s_init AND prev_state /= state THEN + -- WG holds ctrl, when it goes into active state (s_single, s_repeat, or s_calc) + nxt_mon_ctrl <= ctrl; + END IF; + -- These MM ctrl fields always take effect immediately in all WG states + nxt_mon_ctrl.ampl <= ctrl.ampl; + nxt_mon_ctrl.nof_samples <= ctrl.nof_samples; + END PROCESS; + mult : ENTITY common_mult_lib.common_mult GENERIC MAP ( g_technology => g_technology, diff --git a/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd b/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd index 63d02e992cb7517fae7ddb83bbaf8649f71e3e3d..0f4384df6182b31988bb8090ab3bcd95b4835b9b 100644 --- a/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg_wideband.vhd @@ -66,6 +66,7 @@ ENTITY diag_wg_wideband IS st_restart : IN STD_LOGIC; st_ctrl : IN t_diag_wg; + st_mon_ctrl : OUT t_diag_wg; out_ovr : OUT STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); -- big endian, so first output sample in MSBit, MSData out_dat : OUT STD_LOGIC_VECTOR(g_wideband_factor*g_buf_dat_w-1 DOWNTO 0); @@ -88,7 +89,9 @@ ARCHITECTURE str OF diag_wg_wideband IS TYPE t_buf_dat_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); TYPE t_buf_adr_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_addr_w-1 DOWNTO 0); - + + SIGNAL st_mon_ctrl_arr : t_diag_wg_arr(0 TO g_wideband_factor-1); + -- Use same address and data widths for both MM side and ST side memory ports SIGNAL buf_rdval : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); SIGNAL buf_rddata : t_buf_dat_arr(0 TO g_wideband_factor-1); @@ -107,6 +110,8 @@ BEGIN mm_rdval <= buf_rdval(0); mm_rddata <= buf_rddata(0); + st_mon_ctrl <= st_mon_ctrl_arr(0); -- same for all g_wideband_factor waveform generators + gen_wg : FOR I IN 0 TO g_wideband_factor-1 GENERATE -- Waveform buffer u_buf : ENTITY common_lib.common_ram_crw_crw @@ -157,7 +162,8 @@ BEGIN buf_rden => st_rd(I), ctrl => st_ctrl, - + mon_ctrl => st_mon_ctrl_arr(I), + out_ovr => out_ovr( g_wideband_factor-I-1), out_dat => out_dat((g_wideband_factor-I)*g_buf_dat_w-1 DOWNTO (g_wideband_factor-I-1)*g_buf_dat_w), out_val => out_val( g_wideband_factor-I-1), diff --git a/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd b/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd index 4043c51e1efa6bb2bcbf672b4f52ae97dba203a3..c6db7329b6ea11c94d3918d8b6f728518c06230e 100644 --- a/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd +++ b/libraries/base/diag/src/vhdl/diag_wg_wideband_reg.vhd @@ -62,7 +62,8 @@ ENTITY diag_wg_wideband_reg IS sla_out : OUT t_mem_miso; -- actual ranges defined by c_mm_reg -- MM registers in st_clk domain - st_wg_ctrl : OUT t_diag_wg -- WG control port + st_wg_ctrl : OUT t_diag_wg; -- WG control write port + st_mon_ctrl : IN t_diag_wg -- WG control read port, for currently active control ); END diag_wg_wideband_reg; @@ -80,6 +81,8 @@ ARCHITECTURE rtl OF diag_wg_wideband_reg IS SIGNAL mm_wg_ctrl : t_diag_wg; SIGNAL mm_wg_ctrl_mode_wr : STD_LOGIC; + SIGNAL mm_mon_ctrl : t_diag_wg; + -- Registers in st_clk domain BEGIN @@ -129,14 +132,14 @@ BEGIN sla_out.rdval <= '1'; -- c_mm_reg.latency = 1 CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS WHEN 0 => - sla_out.rddata( 7 DOWNTO 0) <= mm_wg_ctrl.mode; -- = 8 = c_diag_wg_mode_w - sla_out.rddata(31 DOWNTO 16) <= mm_wg_ctrl.nof_samples; -- = 16 = c_diag_wg_nof_samples_w + sla_out.rddata( 7 DOWNTO 0) <= mm_mon_ctrl.mode; -- = 8 = c_diag_wg_mode_w + sla_out.rddata(31 DOWNTO 16) <= mm_mon_ctrl.nof_samples; -- = 16 = c_diag_wg_nof_samples_w WHEN 1 => - sla_out.rddata(15 DOWNTO 0) <= mm_wg_ctrl.phase; -- = 16 = c_diag_wg_phase_w + sla_out.rddata(15 DOWNTO 0) <= mm_mon_ctrl.phase; -- = 16 = c_diag_wg_phase_w WHEN 2 => - sla_out.rddata(30 DOWNTO 0) <= mm_wg_ctrl.freq; -- = 31 = c_diag_wg_freq_w + sla_out.rddata(30 DOWNTO 0) <= mm_mon_ctrl.freq; -- = 31 = c_diag_wg_freq_w WHEN 3 => - sla_out.rddata(16 DOWNTO 0) <= mm_wg_ctrl.ampl; -- = 17 = c_diag_wg_ampl_w + sla_out.rddata(16 DOWNTO 0) <= mm_mon_ctrl.ampl; -- = 17 = c_diag_wg_ampl_w WHEN OTHERS => NULL; -- not used MM addresses END CASE; END IF; @@ -161,6 +164,7 @@ BEGIN ------------------------------------------------------------------------------ no_cross : IF g_cross_clock_domain = FALSE GENERATE -- so mm_clk = st_clk + -- Write: MM to ST clock domain p_st_clk : PROCESS(st_rst, st_clk) BEGIN IF st_rst='1' THEN @@ -171,9 +175,13 @@ BEGIN END IF; END IF; END PROCESS; - END GENERATE; -- no_cross - gen_cross : IF g_cross_clock_domain = TRUE GENERATE + -- Read: ST to MM clock domain + mm_mon_ctrl <= st_mon_ctrl; + END GENERATE; + + -- Write: MM to ST clock domain + gen_cross_wr : IF g_cross_clock_domain = TRUE GENERATE -- Assume diag WG mode gets written last, so when diag WG mode is transfered properly to the st_clk domain, then -- the other diag WG control fields are stable as well u_mode : ENTITY common_lib.common_reg_cross_domain @@ -188,7 +196,7 @@ BEGIN out_dat => st_wg_ctrl.mode, out_new => OPEN -- when '1' then the out_dat was updated with in_dat due to in_new ); - END GENERATE; -- gen_cross + END GENERATE; -- The other wg_ctrl only take effect in diag_wg after the mode has been set st_wg_ctrl.nof_samples <= mm_wg_ctrl.nof_samples; @@ -196,4 +204,57 @@ BEGIN st_wg_ctrl.phase <= mm_wg_ctrl.phase; st_wg_ctrl.ampl <= mm_wg_ctrl.ampl; + -- Read: ST to MM clock domain + gen_cross_rd : IF g_cross_clock_domain = TRUE GENERATE + u_mode : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.mode, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.mode + ); + + u_nof_samples : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.nof_samples, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.nof_samples + ); + + u_freq : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.freq, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.freq + ); + + u_phase : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.phase, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.phase + ); + + u_ampl : ENTITY common_lib.common_reg_cross_domain + PORT MAP ( + in_rst => st_rst, + in_clk => st_clk, + in_dat => st_mon_ctrl.ampl, + out_rst => mm_rst, + out_clk => mm_clk, + out_dat => mm_mon_ctrl.ampl + ); + END GENERATE; + END rtl; diff --git a/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd b/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd index 6c6b912bde048cc3c7897963943bbc0c694ae430..e2f291106471290e27750fb6485d82002f149158 100644 --- a/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd +++ b/libraries/base/diag/src/vhdl/mms_diag_wg_wideband.vhd @@ -80,7 +80,8 @@ END mms_diag_wg_wideband; ARCHITECTURE str OF mms_diag_wg_wideband IS - SIGNAL st_wg_ctrl : t_diag_wg; + SIGNAL st_wg_ctrl : t_diag_wg; -- write + SIGNAL st_mon_ctrl : t_diag_wg; -- read BEGIN @@ -100,7 +101,8 @@ BEGIN sla_out => reg_miso, -- MM registers in st_clk domain - st_wg_ctrl => st_wg_ctrl + st_wg_ctrl => st_wg_ctrl, + st_mon_ctrl => st_mon_ctrl ); u_wg_wideband : ENTITY work.diag_wg_wideband @@ -137,6 +139,7 @@ BEGIN st_restart => st_restart, st_ctrl => st_wg_ctrl, + st_mon_ctrl => st_mon_ctrl, out_ovr => out_ovr, out_dat => out_dat, diff --git a/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd b/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd index ca3ba5ef9857a8cd8b962bf3fb7aa4f4a450445f..520bf017d12372c674ac709130a7c0fc01bde844 100644 --- a/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd +++ b/libraries/base/diag/tb/vhdl/tb_diag_wg.vhd @@ -19,7 +19,7 @@ -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -------------------------------------------------------------------------------- - + LIBRARY IEEE, common_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; @@ -49,7 +49,7 @@ ARCHITECTURE tb OF tb_diag_wg IS CONSTANT c_clk_freq : NATURAL := 200*10**6; -- Hz CONSTANT c_clk_period : TIME := (10**9 / c_clk_freq) * 1 ns; - + -- Default settings CONSTANT c_buf : t_c_mem := (latency => 1, adr_w => g_buf_adr_w, @@ -59,86 +59,86 @@ ARCHITECTURE tb OF tb_diag_wg IS CONSTANT c_buf_file : STRING := sel_a_b(c_buf.adr_w=11 AND c_buf.dat_w=18, "data/diag_sin_2048x18.hex", sel_a_b(c_buf.adr_w=10 AND c_buf.dat_w=18, "data/diag_sin_1024x18.hex", sel_a_b(c_buf.adr_w=10 AND c_buf.dat_w= 8, "data/diag_sin_1024x8.hex", "UNUSED"))); - - + + CONSTANT c_wg_nof_samples : NATURAL := c_buf.nof_dat; -- must be <= c_buf.nof_dat CONSTANT c_wg_gain_w : NATURAL := 1; -- Normalized range [0 1> maps to fixed point range [0:2**c_diag_wg_ampl_w> -- . use gain 2**0 = 1 to have fulle scale without clipping -- . use gain 2**g_calc_gain_w > 1 to cause clipping - + CONSTANT c_buf_full_scale : NATURAL := 2**(g_buf_dat_w-1)-1; -- The stored waveform range should also be [-c_buf_full_scale +c_buf_full_scale], so not including -c_buf_full_scale-1 CONSTANT c_wg_full_scale : NATURAL := 2**(g_wg_dat_w-1)-1; CONSTANT c_ampl_norm : REAL := sel_a_b(g_wg_dat_w < g_buf_dat_w, REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1), 1.0); --CONSTANT c_ampl_norm : REAL := REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1); -- Use this if g_wg_dat_w < g_buf_dat_w, to avoid clipping --CONSTANT c_ampl_norm : REAL := 1.0; -- Use this if g_wg_dat_w = g_buf_dat_w, because the stored waveform range is already -+c_buf_full_scale --CONSTANT c_ampl_norm : REAL := REAL(c_buf_full_scale)/REAL(c_buf_full_scale+1); -- No need to use this, because the stored waveform range is already -+c_buf_full_scale - + CONSTANT c_freq_unit : REAL := c_diag_wg_freq_unit; -- ^= c_clk_freq = Fs (sample frequency), assuming one sinus waveform in the buffer CONSTANT c_ampl_unit : REAL := c_diag_wg_ampl_unit*c_ampl_norm; -- ^= Full Scale range [-c_wg_full_scale +c_wg_full_scale] without clipping CONSTANT c_phase_unit : REAL := c_diag_wg_phase_unit; -- ^= 1 degree - + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL restart : STD_LOGIC; - + SIGNAL buf_rddat : STD_LOGIC_VECTOR(c_buf.dat_w-1 DOWNTO 0); SIGNAL buf_rdval : STD_LOGIC; SIGNAL buf_addr : STD_LOGIC_VECTOR(c_buf.adr_w-1 DOWNTO 0); SIGNAL buf_rden : STD_LOGIC; - + SIGNAL wg_ctrl : t_diag_wg; - + SIGNAL wg_mode : NATURAL; SIGNAL wg_freq : NATURAL; SIGNAL wg_ampl : NATURAL; SIGNAL wg_nof_samples : NATURAL; SIGNAL wg_phase : NATURAL; - + SIGNAL wg_ovr : STD_LOGIC; SIGNAL wg_dat : STD_LOGIC_VECTOR(c_buf.dat_w-1 DOWNTO 0); SIGNAL wg_val : STD_LOGIC; SIGNAL wg_sync : STD_LOGIC; - + BEGIN rst <= '1', '0' AFTER c_clk_period/10; clk <= NOT clk OR tb_end AFTER c_clk_period/2; - + wg_ctrl.mode <= TO_UVEC(wg_mode, c_diag_wg_mode_w); wg_ctrl.freq <= TO_UVEC(wg_freq, c_diag_wg_freq_w); wg_ctrl.ampl <= TO_UVEC(wg_ampl, c_diag_wg_ampl_w); wg_ctrl.nof_samples <= TO_UVEC(wg_nof_samples, c_diag_wg_nofsamples_w); wg_ctrl.phase <= TO_UVEC(wg_phase, c_diag_wg_phase_w); - + p_mm : PROCESS BEGIN tb_end <= '0'; restart <= '0'; wg_mode <= c_diag_wg_mode_off; - + --------------------------------------------------------------------------- -- >>> Single, repeat mode wg_nof_samples <= c_wg_nof_samples; - + -- >>> CALC mode -- Cosinus with frequency Fs/2 (note sinus Fs/2 yields DC = 0) -- wg_freq <= INTEGER(0.5 * c_freq_unit); -- wg_phase <= INTEGER(90.0 * c_phase_unit); - + -- Choosing 1.0*Fs to select Fs which is equivalent to DC, hence the DC value is then determined by phase - -- this also applies to 2.0, 3.0, 4.0 etc + -- this also applies to 2.0, 3.0, 4.0 etc -- wg_freq <= INTEGER(1.0 * c_freq_unit); -- wg_phase <= INTEGER(45.0 * c_phase_unit); - + -- Sinus Fs/16 wg_freq <= INTEGER(0.0625 * c_freq_unit); --wg_freq <= INTEGER(511.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0); -- minimum value, yields Fs/c_freq_unit Hz sinus wg_phase <= INTEGER(0.0 * c_phase_unit); - + -- Sinus Fs/17 -- wg_freq <= INTEGER(1.0/17.0 * c_freq_unit); -- wg_phase <= INTEGER(0.0 * c_phase_unit); @@ -146,13 +146,13 @@ BEGIN wg_ampl <= INTEGER(1.0 * c_ampl_unit); -- yields amplitude of c_wg_full_scale -- wg_ampl <= INTEGER(1.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 1 -- wg_ampl <= INTEGER(3.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 3 - + WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT FOR c_clk_period*200; - + --------------------------------------------------------------------------- -- >>> Select the different modes - + -- CALC mode wg_mode <= c_diag_wg_mode_calc; restart <= '1'; @@ -164,14 +164,14 @@ BEGIN restart <= '0'; WAIT FOR c_clk_period*3000; --WAIT FOR 1 sec; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; WAIT FOR c_clk_period*200; - + -- SINGLE mode wg_mode <= c_diag_wg_mode_single; FOR I IN 0 TO 1 LOOP @@ -181,7 +181,7 @@ BEGIN WAIT FOR c_clk_period*c_buf.nof_dat; WAIT FOR c_clk_period*300; END LOOP; - + -- REPEAT mode wg_mode <= c_diag_wg_mode_repeat; restart <= '1'; @@ -194,19 +194,19 @@ BEGIN restart <= '0'; WAIT FOR c_clk_period*c_buf.nof_dat*5; WAIT FOR c_clk_period*200; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*100; tb_end <= '1'; WAIT; END PROCESS; - + -- Waveform buffer u_buf : ENTITY common_lib.common_ram_crw_crw GENERIC MAP ( @@ -231,7 +231,7 @@ BEGIN rd_val_a => OPEN, rd_val_b => buf_rdval ); - + -- Waveform generator u_wg : ENTITY work.diag_wg GENERIC MAP ( @@ -258,6 +258,6 @@ BEGIN out_val => wg_val, out_sync => wg_sync ); - + END tb; diff --git a/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd b/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd index 5fe5307223af3b54807bffcd691fe80b30ea4130..3727020eac42f779201e4a94f5d043d0b93ec80d 100644 --- a/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd +++ b/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd @@ -19,7 +19,15 @@ -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- -------------------------------------------------------------------------------- - +-- Purpose: Tb for WG +-- Description: Verifies all WG modes. +-- Usage: +-- > as 10 +-- > run -all +-- . Use select rigth mouse in Wave window on wg_dat and choose radix --> +-- decimal and format --> analogue (automatic) +-- . Observe state in diag_wg(0). + LIBRARY IEEE, common_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; @@ -27,15 +35,6 @@ USE IEEE.MATH_REAL.ALL; USE common_lib.common_pkg.ALL; USE work.diag_pkg.ALL; --- Usage: --- > do wave_diag_wg_wideband.do --- > run -all --- --- . Use select rigth mouse in wave window on wg_dat and choose 'format --> analogue (automatic)' --- . run 10 us to see CALC mode waveform output at proper automatic scale --- . run 100 us to see SINGLE and REPEAT mode waveform output at proper automatic scale - - ENTITY tb_diag_wg_wideband IS GENERIC ( -- Wideband parameters @@ -52,49 +51,51 @@ ARCHITECTURE tb OF tb_diag_wg_wideband IS CONSTANT c_clk_freq : NATURAL := 200; -- MHz CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; - + -- Default WG settings CONSTANT c_buf_nof_dat : NATURAL := 2**g_buf_addr_w; - + CONSTANT c_wg_gain_w : NATURAL := 1; -- Normalized range [0 1> maps to fixed point range [0:2**c_diag_wg_ampl_w> -- . use gain 2**0 = 1 to have fulle scale without clipping -- . use gain 2**g_calc_gain_w > 1 to cause clipping - + CONSTANT c_buf_full_scale : NATURAL := 2**(g_buf_dat_w-1)-1; -- The stored waveform range should also be [-c_buf_full_scale +c_buf_full_scale], so not including -c_buf_full_scale-1 CONSTANT c_wg_full_scale : NATURAL := 2**(g_wg_dat_w-1)-1; CONSTANT c_ampl_norm : REAL := sel_a_b(g_wg_dat_w < g_buf_dat_w, REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1), 1.0); --CONSTANT c_ampl_norm : REAL := REAL(c_wg_full_scale)/REAL(c_wg_full_scale+1); -- Use this if g_wg_dat_w < g_buf_dat_w, to avoid clipping --CONSTANT c_ampl_norm : REAL := 1.0; -- Use this if g_wg_dat_w = g_buf_dat_w, because the stored waveform range is already -+c_buf_full_scale --CONSTANT c_ampl_norm : REAL := REAL(c_buf_full_scale)/REAL(c_buf_full_scale+1); -- No need to use this, because the stored waveform range is already -+c_buf_full_scale - + CONSTANT c_freq_unit : REAL := c_diag_wg_freq_unit; -- ^= c_clk_freq = Fs (sample frequency), assuming one sinus waveform in the buffer CONSTANT c_ampl_unit : REAL := c_diag_wg_ampl_unit*c_ampl_norm; -- ^= Full Scale range [-c_wg_full_scale +c_wg_full_scale] without clipping CONSTANT c_phase_unit : REAL := c_diag_wg_phase_unit; -- ^= 1 degree - + -- Wideband WG settings CONSTANT c_sample_period : TIME := (10**6 / (c_clk_freq*g_wideband_factor)) * 1 ps; - + TYPE t_buf_dat_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); - + SIGNAL tb_end : STD_LOGIC; SIGNAL rst : STD_LOGIC; SIGNAL clk : STD_LOGIC := '1'; SIGNAL restart : STD_LOGIC; - + SIGNAL wg_ctrl : t_diag_wg; - + SIGNAL cur_ctrl : t_diag_wg; + SIGNAL mon_ctrl : t_diag_wg; + SIGNAL wg_mode : NATURAL; SIGNAL wg_freq : NATURAL; SIGNAL wg_ampl : NATURAL; SIGNAL wg_nof_samples : NATURAL; SIGNAL wg_phase : NATURAL; - + -- Wideband WG output is big endian, so first output sample in MSBit, MSData SIGNAL out_ovr : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); SIGNAL out_dat : STD_LOGIC_VECTOR(g_wideband_factor*g_buf_dat_w-1 DOWNTO 0); SIGNAL out_val : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); SIGNAL out_sync : STD_LOGIC_VECTOR(g_wideband_factor -1 DOWNTO 0); - + SIGNAL wg_ovr : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); SIGNAL wg_dat : t_buf_dat_arr(0 TO g_wideband_factor-1); SIGNAL wg_val : STD_LOGIC_VECTOR(0 TO g_wideband_factor-1); @@ -106,47 +107,47 @@ ARCHITECTURE tb OF tb_diag_wg_wideband IS SIGNAL sample_dat : STD_LOGIC_VECTOR(g_buf_dat_w-1 DOWNTO 0); SIGNAL sample_val : STD_LOGIC; SIGNAL sample_sync : STD_LOGIC; - + BEGIN rst <= '1', '0' AFTER c_clk_period/10; clk <= NOT clk OR tb_end AFTER c_clk_period/2; - + sample_clk <= NOT sample_clk OR tb_end AFTER c_sample_period/2; - + wg_ctrl.mode <= TO_UVEC(wg_mode, c_diag_wg_mode_w); wg_ctrl.freq <= TO_UVEC(wg_freq, c_diag_wg_freq_w); wg_ctrl.ampl <= TO_UVEC(wg_ampl, c_diag_wg_ampl_w); wg_ctrl.nof_samples <= TO_UVEC(wg_nof_samples, c_diag_wg_nofsamples_w); wg_ctrl.phase <= TO_UVEC(wg_phase, c_diag_wg_phase_w); - + p_mm : PROCESS BEGIN tb_end <= '0'; restart <= '0'; wg_mode <= c_diag_wg_mode_off; - + --------------------------------------------------------------------------- -- >>> Single, repeat mode wg_nof_samples <= c_buf_nof_dat; -- must be <= c_buf_nof_dat - + -- >>> CALC mode -- Cosinus with frequency Fs/2 (note sinus Fs/2 yields DC = 0) -- wg_freq <= INTEGER(0.5 * c_freq_unit); -- wg_phase <= INTEGER(90.0 * c_phase_unit); - + -- Choosing 1.0*Fs to select Fs which is equivalent to DC, hence the DC value is then determined by phase - -- this also applies to 2.0, 3.0, 4.0 etc + -- this also applies to 2.0, 3.0, 4.0 etc -- wg_freq <= INTEGER(1.0 * c_freq_unit); -- wg_phase <= INTEGER(45.0 * c_phase_unit); - + -- Sinus Fs/16 wg_freq <= INTEGER(0.0625 * c_freq_unit); --wg_freq <= INTEGER(511.0/512.0 * c_freq_unit); wg_freq <= INTEGER(1.0/512.0 * c_freq_unit); --wg_freq <= INTEGER(1.0); -- minimum value, yields Fs/c_freq_unit Hz sinus wg_phase <= INTEGER(0.0 * c_phase_unit); - + -- Sinus Fs/17 -- wg_freq <= INTEGER(1.0/17.0 * c_freq_unit); -- wg_phase <= INTEGER(0.0 * c_phase_unit); @@ -154,68 +155,115 @@ BEGIN wg_ampl <= INTEGER(1.0 * c_ampl_unit); -- yields amplitude of c_wg_full_scale -- wg_ampl <= INTEGER(1.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 1 -- wg_ampl <= INTEGER(3.0/REAL(c_wg_full_scale) * c_ampl_unit); -- yields amplitude of 3 - + WAIT UNTIL rising_edge(clk); -- align to rising edge + cur_ctrl <= wg_ctrl; WAIT FOR c_clk_period*200; - + --------------------------------------------------------------------------- -- >>> Select the different modes - + -- CALC mode wg_mode <= c_diag_wg_mode_calc; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC)" SEVERITY ERROR; + WAIT FOR c_clk_period*3000; + + wg_ampl <= INTEGER(0.5 * c_ampl_unit); -- change ampl immediately + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC ampl)" SEVERITY ERROR; + + WAIT FOR c_clk_period*3000; + + wg_phase <= INTEGER(90.0 * c_phase_unit); -- no change phase without restart + wg_freq <= INTEGER(0.5/512.0 * c_freq_unit); -- no change freq without restart + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold CALC phase and freq)" SEVERITY ERROR; + + WAIT FOR c_clk_period*3000; + restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new CALC phase and freq)" SEVERITY ERROR; + WAIT FOR c_clk_period*3000; - --WAIT FOR 1 sec; - + -- OFF mode wg_mode <= c_diag_wg_mode_off; + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; -- OFF mode takes effect immediately + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected immediately OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected still OFF)" SEVERITY ERROR; + WAIT FOR c_clk_period*200; - + -- SINGLE mode wg_mode <= c_diag_wg_mode_single; - FOR I IN 0 TO 1 LOOP + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold OFF)" SEVERITY ERROR; + FOR I IN 0 TO 3 LOOP restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new SINGLE)" SEVERITY ERROR; WAIT FOR c_clk_period*c_buf_nof_dat; WAIT FOR c_clk_period*300; END LOOP; - + -- REPEAT mode wg_mode <= c_diag_wg_mode_repeat; - restart <= '1'; - WAIT FOR c_clk_period*1; - restart <= '0'; - WAIT FOR c_clk_period*c_buf_nof_dat*5; - WAIT FOR c_clk_period*200; - restart <= '1'; - WAIT FOR c_clk_period*1; - restart <= '0'; - WAIT FOR c_clk_period*c_buf_nof_dat*5; - WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected hold SINGLE)" SEVERITY ERROR; + FOR I IN 0 TO 1 LOOP + restart <= '1'; + WAIT FOR c_clk_period*1; + restart <= '0'; + cur_ctrl <= wg_ctrl; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected new REPEAT)" SEVERITY ERROR; + WAIT FOR c_clk_period*c_buf_nof_dat*5; + WAIT FOR c_clk_period*200; + END LOOP; + -- OFF mode wg_mode <= c_diag_wg_mode_off; + WAIT FOR c_clk_period*1; + cur_ctrl <= wg_ctrl; -- OFF mode takes effect immediately, no need for restart + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected immediately OFF)" SEVERITY ERROR; restart <= '1'; WAIT FOR c_clk_period*1; restart <= '0'; + WAIT FOR c_clk_period*10; + ASSERT mon_ctrl = cur_ctrl REPORT "Wrong mon_ctrl (expected still OFF)" SEVERITY ERROR; + WAIT FOR c_clk_period*200; - + WAIT FOR c_clk_period*100; tb_end <= '1'; WAIT; END PROCESS; - - + + u_wideband_wg : ENTITY work.diag_wg_wideband GENERIC MAP ( -- Wideband parameters @@ -231,7 +279,7 @@ BEGIN -- Memory-mapped clock domain mm_rst => '0', mm_clk => '0', - + mm_wrdata => (OTHERS=>'0'), mm_address => (OTHERS=>'0'), mm_wr => '0', @@ -243,15 +291,16 @@ BEGIN st_rst => rst, st_clk => clk, st_restart => restart, - + st_ctrl => wg_ctrl, + st_mon_ctrl => mon_ctrl, out_ovr => out_ovr, out_dat => out_dat, out_val => out_val, out_sync => out_sync ); - + -- Map wideband WG out_* slv to wg_* arrays to ease interpretation in wave window gen_wires : FOR I IN 0 TO g_wideband_factor-1 GENERATE wg_ovr(I) <= out_ovr( g_wideband_factor-I-1); @@ -259,8 +308,8 @@ BEGIN wg_val(I) <= out_val( g_wideband_factor-I-1); wg_sync(I) <= out_sync( g_wideband_factor-I-1); END GENERATE; - - -- View WG output at the sample rate + + -- View WG output at the sample rate p_sample : PROCESS(sample_clk) BEGIN IF rising_edge(sample_clk) THEN @@ -275,6 +324,6 @@ BEGIN sample_sync <= wg_sync(sample_cnt); END IF; END PROCESS; - + END tb; diff --git a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd index 0d5b21ea615ec19a28357937cc811b4c43b23ddc..22099bf168a065ce4064308f9e30c4a84b12f1e0 100644 --- a/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/src/vhdl/dp_bsn_sync_scheduler.vhd @@ -111,29 +111,31 @@ USE work.dp_stream_pkg.ALL; ENTITY dp_bsn_sync_scheduler IS GENERIC ( - g_bsn_w : NATURAL := c_dp_stream_bsn_w; - g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 - g_pipeline : NATURAL := 1 -- use '1' on HW, use '0' for easier debugging in Wave window + g_bsn_w : NATURAL := c_dp_stream_bsn_w; + g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 + g_ctrl_interval_size_min : NATURAL := 1; -- Minimum interval size to use if MM write interval size is set too small. + g_pipeline : NATURAL := 1 -- use '1' on HW, use '0' for easier debugging in Wave window ); PORT ( - rst : IN STD_LOGIC; - clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; -- M&C - ctrl_enable : IN STD_LOGIC; - ctrl_enable_evt : IN STD_LOGIC; - ctrl_interval_size : IN NATURAL; - ctrl_start_bsn : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); - mon_current_input_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - mon_input_bsn_at_sync : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - mon_output_enable : OUT STD_LOGIC; - mon_output_sync_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + ctrl_enable : IN STD_LOGIC; + ctrl_enable_evt : IN STD_LOGIC; + ctrl_interval_size : IN NATURAL; + ctrl_start_bsn : IN STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); + mon_current_input_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + mon_input_bsn_at_sync : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + mon_output_enable : OUT STD_LOGIC; + mon_output_interval_size : OUT NATURAL; + mon_output_sync_bsn : OUT STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- Streaming - in_sosi : IN t_dp_sosi; - out_sosi : OUT t_dp_sosi; - out_start : OUT STD_LOGIC; -- pulse at out_sosi.sync at ctrl_start_bsn - out_enable : OUT STD_LOGIC -- for tb verification purposes + in_sosi : IN t_dp_sosi; + out_sosi : OUT t_dp_sosi; + out_start : OUT STD_LOGIC; -- pulse at out_sosi.sync at ctrl_start_bsn + out_enable : OUT STD_LOGIC -- for tb verification purposes ); END dp_bsn_sync_scheduler; @@ -158,7 +160,7 @@ ARCHITECTURE rtl OF dp_bsn_sync_scheduler IS output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); END RECORD; - CONSTANT c_reg_rst : t_reg := ('0', '0', 0, 0, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); + CONSTANT c_reg_rst : t_reg := ('0', '0', 0, g_ctrl_interval_size_min, (OTHERS=>'0'), (OTHERS=>'0'), 0, 0, 0, 0, 0, '1', '0', '0', (OTHERS=>'0')); -- Local registers SIGNAL r : t_reg; @@ -173,10 +175,11 @@ BEGIN ASSERT g_block_size >= 2 REPORT "g_block_size must be >= 2." SEVERITY FAILURE; -- Capture monitoring info - mon_current_input_bsn <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sop = '1'; - mon_input_bsn_at_sync <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sync = '1'; - mon_output_enable <= r.output_enable; - mon_output_sync_bsn <= r.output_sync_bsn; + mon_current_input_bsn <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sop = '1'; + mon_input_bsn_at_sync <= in_sosi.bsn(g_bsn_w-1 DOWNTO 0) WHEN rising_edge(clk) AND in_sosi.sync = '1'; + mon_output_enable <= r.output_enable; + mon_output_interval_size <= g_ctrl_interval_size_min WHEN rst='1' ELSE r.interval_size WHEN rising_edge(clk) AND output_start = '1'; + mon_output_sync_bsn <= r.output_sync_bsn; p_clk : PROCESS(rst, clk) BEGIN diff --git a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd index 75b42316d077b32591da03f6a12aff7ee6da26d9..9cfe48f8dba79806999f160015e2e625b4753190 100644 --- a/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/src/vhdl/mmp_dp_bsn_sync_scheduler.vhd @@ -22,7 +22,8 @@ -- -- wi Bits Access Type Name -- 0 [0] RW boolean ctrl_enable, '1' is on, '0' is FALSE is off --- 1 [31:0] RW uint32 ctrl_interval_size +-- 1 [31:0] RW uint32 W: ctrl_interval_size +-- R: mon_output_interval_size -- 2 [31:0] RW uint64 ctrl_start_bsn[31:0] -- 3 [31:0] RW ctrl_start_bsn[63:32] -- 4 [31:0] RO uint64 mon_current_input_bsn[31:0] @@ -63,7 +64,7 @@ USE work.dp_stream_pkg.ALL; ENTITY mmp_dp_bsn_sync_scheduler IS GENERIC ( g_bsn_w : NATURAL := c_dp_stream_bsn_w; - g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 + g_block_size : NATURAL := 256; -- = number of data valid per BSN block, must be >= 2 g_ctrl_interval_size_min : NATURAL := 1 -- Minimum interval size to use if MM write interval size is set too small. ); PORT ( @@ -95,20 +96,21 @@ ARCHITECTURE str OF mmp_dp_bsn_sync_scheduler IS -- init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X' CONSTANT c_mm_reg : t_c_mem := (1, 4, c_word_w, 12, '0'); - SIGNAL reg_wr_arr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat -1 DOWNTO 0); - SIGNAL reg_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0); - SIGNAL reg_rd : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); - - SIGNAL wr_ctrl_enable : STD_LOGIC; - SIGNAL wr_ctrl_enable_evt : STD_LOGIC; - SIGNAL ctrl_enable : STD_LOGIC := '0'; - SIGNAL ctrl_enable_evt : STD_LOGIC := '0'; - SIGNAL ctrl_interval_size : NATURAL; - SIGNAL ctrl_start_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); - SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); - SIGNAL mon_output_enable : STD_LOGIC; - SIGNAL mon_output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL reg_wr_arr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat -1 DOWNTO 0); + SIGNAL reg_wr : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0); + SIGNAL reg_rd : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL wr_ctrl_enable : STD_LOGIC; + SIGNAL wr_ctrl_enable_evt : STD_LOGIC; + SIGNAL ctrl_enable : STD_LOGIC := '0'; + SIGNAL ctrl_enable_evt : STD_LOGIC := '0'; + SIGNAL ctrl_interval_size : NATURAL; + SIGNAL ctrl_start_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL mon_current_input_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL mon_input_bsn_at_sync : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); + SIGNAL mon_output_enable : STD_LOGIC; + SIGNAL mon_output_interval_size : NATURAL; + SIGNAL mon_output_sync_bsn : STD_LOGIC_VECTOR(g_bsn_w-1 DOWNTO 0); -- Resize BSN values to 64 bit SIGNAL wr_start_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); @@ -151,7 +153,7 @@ BEGIN -- . Read reg_rd( 0) <= ctrl_enable; -- read back internal ctrl_enable - reg_rd( 2*c_word_w-1 DOWNTO 1*c_word_w) <= TO_UVEC(ctrl_interval_size, c_word_w); + reg_rd( 2*c_word_w-1 DOWNTO 1*c_word_w) <= TO_UVEC(mon_output_interval_size, c_word_w); reg_rd( 3*c_word_w-1 DOWNTO 2*c_word_w) <= wr_start_bsn_64( c_word_w-1 DOWNTO 0); -- low word reg_rd( 4*c_word_w-1 DOWNTO 3*c_word_w) <= wr_start_bsn_64( 2*c_word_w-1 DOWNTO c_word_w); -- high word reg_rd( 5*c_word_w-1 DOWNTO 4*c_word_w) <= rd_current_input_bsn_64( c_word_w-1 DOWNTO 0); -- low word @@ -189,29 +191,31 @@ BEGIN u_dp_bsn_sync_scheduler : ENTITY work.dp_bsn_sync_scheduler GENERIC MAP ( - g_bsn_w => g_bsn_w, - g_block_size => g_block_size, - g_pipeline => 1 + g_bsn_w => g_bsn_w, + g_block_size => g_block_size, + g_ctrl_interval_size_min => g_ctrl_interval_size_min, + g_pipeline => 1 ) PORT MAP ( - rst => dp_rst, - clk => dp_clk, + rst => dp_rst, + clk => dp_clk, -- M&C - ctrl_enable => ctrl_enable, - ctrl_enable_evt => ctrl_enable_evt, - ctrl_interval_size => ctrl_interval_size, - ctrl_start_bsn => ctrl_start_bsn, - mon_current_input_bsn => mon_current_input_bsn, - mon_input_bsn_at_sync => mon_input_bsn_at_sync, - mon_output_enable => mon_output_enable, - mon_output_sync_bsn => mon_output_sync_bsn, + ctrl_enable => ctrl_enable, + ctrl_enable_evt => ctrl_enable_evt, + ctrl_interval_size => ctrl_interval_size, + ctrl_start_bsn => ctrl_start_bsn, + mon_current_input_bsn => mon_current_input_bsn, + mon_input_bsn_at_sync => mon_input_bsn_at_sync, + mon_output_enable => mon_output_enable, + mon_output_interval_size => mon_output_interval_size, + mon_output_sync_bsn => mon_output_sync_bsn, -- Streaming - in_sosi => in_sosi, - out_sosi => out_sosi, - out_start => out_start, - out_enable => out_enable + in_sosi => in_sosi, + out_sosi => out_sosi, + out_start => out_start, + out_enable => out_enable ); END str; diff --git a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd index ce4e5f605e7efbba13cb3ec7a972a5d9b9548805..43162d9c6df7dd1b3e4b768e0353f9f65d51e791 100644 --- a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd +++ b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_sync_scheduler.vhd @@ -52,6 +52,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_sync_scheduler IS CONSTANT c_nof_block_per_input_sync : NATURAL := 17; CONSTANT c_nof_block_per_output_sync : NATURAL := 5; CONSTANT c_block_size : NATURAL := 10; + CONSTANT c_ctrl_interval_size_min : NATURAL := 19; -- Minimum interval size to use if MM write interval size is set too small. CONSTANT c_input_gap_size : NATURAL := 3; CONSTANT c_sim_nof_blocks : NATURAL := c_nof_block_per_input_sync * c_nof_input_sync; @@ -75,6 +76,7 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_sync_scheduler IS SIGNAL ctrl_start_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_output_enable : STD_LOGIC; + SIGNAL mon_output_interval_size : NATURAL; SIGNAL mon_current_input_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_input_bsn_at_sync_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); SIGNAL mon_output_sync_bsn_64 : STD_LOGIC_VECTOR(2*c_word_w-1 DOWNTO 0); @@ -118,6 +120,13 @@ BEGIN proc_common_wait_some_cycles(mm_clk, 1); ASSERT mon_block_size = c_block_size REPORT "Wrong block_size." SEVERITY ERROR; + -- . Read mon_output_interval_size + proc_mem_mm_bus_rd(1, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + mon_output_interval_size <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)); + proc_common_wait_some_cycles(mm_clk, 1); + ASSERT mon_output_interval_size = c_ctrl_interval_size_min REPORT "Wrong minimum output interval_size." SEVERITY ERROR; + -- . Read mon_output_enable proc_mem_mm_bus_rd(8, mm_clk, reg_miso, reg_mosi); proc_mem_mm_bus_rd_latency(1, mm_clk); @@ -214,10 +223,16 @@ BEGIN proc_mem_mm_bus_rd_latency(1, mm_clk); mon_output_enable <= reg_miso.rddata(0); + -- . Read mon_output_interval_size + proc_mem_mm_bus_rd(1, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + mon_output_interval_size <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)); + -- Verify output is on and running proc_common_wait_some_cycles(mm_clk, 1); ASSERT mon_output_enable = '1' REPORT "mon_output_enable is not enabled." SEVERITY ERROR; ASSERT out_enable = '1' REPORT "output_enable is not enabled." SEVERITY ERROR; + ASSERT mon_output_interval_size = c_ctrl_interval_size REPORT "mon_output_interval_size is not ctrl_interval_size." SEVERITY ERROR; --------------------------------------------------------------------------- -- Check that monitor BSN are incrementing @@ -381,8 +396,9 @@ BEGIN u_mmp_dp_bsn_sync_scheduler : ENTITY work.mmp_dp_bsn_sync_scheduler GENERIC MAP ( - g_bsn_w => c_bsn_w, - g_block_size => c_block_size + g_bsn_w => c_bsn_w, + g_block_size => c_block_size, + g_ctrl_interval_size_min => c_ctrl_interval_size_min ) PORT MAP ( -- Clocks and reset