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_wideband.vhd b/libraries/base/diag/tb/vhdl/tb_diag_wg_wideband.vhd index 5c61df80911bbb577fa475b7d7450b1f33b1f56b..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,6 +19,14 @@ -- 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; @@ -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 @@ -82,6 +81,8 @@ ARCHITECTURE tb OF tb_diag_wg_wideband IS 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; @@ -156,6 +157,7 @@ BEGIN -- 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; --------------------------------------------------------------------------- @@ -163,51 +165,97 @@ BEGIN -- 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; @@ -245,6 +293,7 @@ BEGIN st_restart => restart, st_ctrl => wg_ctrl, + st_mon_ctrl => mon_ctrl, out_ovr => out_ovr, out_dat => out_dat,