diff --git a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd index b57dfae71f231ec089451bbb1190f7fba3c1e333..72b57c476afcbf4d9027ee67b90776f57d7396ee 100644 --- a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd +++ b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd @@ -310,11 +310,11 @@ BEGIN END LOOP; - WAIT FOR c_mm_clk_period*2200; + WAIT FOR c_mm_clk_period*2500; mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 1, tb_clk); WAIT FOR c_mm_clk_period*300; mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 0, tb_clk); - WAIT FOR c_mm_clk_period*55000; + WAIT FOR c_mm_clk_period*52000; assert false report "3. read whole memory!" severity note; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd index c203779dc90592cad0c92cedb4dd904cd8c7f4b8..edd0f6c160c3e64582a6e4c1e1241984adf7bb1f 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd @@ -98,7 +98,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w(g_tech_ddr); -- 576 -- type for statemachine - TYPE t_state IS (RESET, WAIT_FOR_SOP, START_WRITING, WRITING, SET_STOP, STOP_WRITING, LAST_WRITE_BURST, START_READING, READING, STOP_READING, IDLE); + TYPE t_state IS (RESET, STOP_READING, WAIT_FOR_SOP, WRITING, SET_STOP, STOP_WRITING, LAST_WRITE_BURST, START_READING, READING); -- record for readability TYPE t_reg IS RECORD @@ -128,7 +128,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS wr_sosi : t_dp_sosi; END RECORD; - CONSTANT c_t_reg_init : t_reg := (RESET, '0', '0', TO_UVEC(g_max_adr, c_adr_w), (OTHERS => '0'), 0, '1', '1', '0', 0, (OTHERS => '0'), 0, '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init); + CONSTANT c_t_reg_init : t_reg := (RESET, '0', '0', TO_UVEC(g_max_adr, c_adr_w), (OTHERS => '0'), 0, '1', '1', '0', 0, (OTHERS => '0'), 0, '1', c_mem_ctlr_mosi_rst, c_dp_sosi_init); -- signals for readability @@ -159,37 +159,43 @@ BEGIN v.dvr_mosi.wr := '1'; v.wr_sosi.valid := '1'; - - WHEN WAIT_FOR_SOP => - v.dvr_mosi.burstbegin := '0'; - v.rst_ddrctrl_input := '0'; - IF q_reg.started = '0' AND inp_sosi.eop = '1' THEN - v.wr_sosi.valid := '1'; - ELSIF inp_sosi.sop = '1' THEN - v.state := WRITING; --START_WRITING; - ELSE - v.wr_sosi.valid := '0'; - v.state := WAIT_FOR_SOP; - END IF; - + IF rst = '0' THEN + v.state := STOP_READING; + END IF; - WHEN START_WRITING => - -- this state generates the first write burst. - IF q_reg.wr_bursts_ready >= 1 AND dvr_miso.done = '1' AND v.wr_burst_en = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN - v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(TO_UINT(q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0))+q_reg.stop_burstsize, c_adr_w); - v.dvr_mosi.wr := '1'; - v.dvr_mosi.rd := '0'; + WHEN STOP_READING => + -- this is the last read burst, this make sure every data containing word in the memory has been read. + IF TO_UINT(rd_fifo_usedw) <= g_burstsize AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN v.dvr_mosi.burstbegin := '1'; - v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := TO_UVEC(g_burstsize-q_reg.stop_burstsize, dvr_mosi.burstsize'length); - v.wr_burst_en := '0'; + v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0); + v.dvr_mosi.burstsize := TO_UVEC(q_reg.stop_burstsize, dvr_mosi.burstsize'length); + v.stopped := '0'; + v.wr_sosi.valid := '0'; + v.state := WAIT_FOR_SOP; v.wr_burst_en := '1'; - v.state := WRITING; + v.rst_ddrctrl_input := '1'; ELSE v.dvr_mosi.burstbegin := '0'; - v.state := START_WRITING; END IF; - v.wr_bursts_ready := TO_UINT(wr_fifo_usedw(g_wr_fifo_uw_w-1 DOWNTO c_bitshift_w)); + v.dvr_mosi.wr := '0'; + v.dvr_mosi.rd := '1'; + + IF dvr_miso.done = '0' THEN + v.rd_burst_en := '1'; + END IF; + + + WHEN WAIT_FOR_SOP => + v.dvr_mosi.burstbegin := '0'; + v.rst_ddrctrl_input := '0'; + IF q_reg.started = '0' AND inp_sosi.eop = '1' THEN + v.wr_sosi.valid := '1'; + ELSIF inp_sosi.sop = '1' THEN + v.state := WRITING; + ELSE + v.wr_sosi.valid := '0'; + END IF; WHEN WRITING => @@ -222,12 +228,10 @@ BEGIN v.ready_for_set_stop := '1'; END IF; - IF q_reg.ready_for_set_stop = '1' AND inp_sosi.eop = '1' THEN + IF q_reg.ready_for_set_stop = '1' AND inp_sosi.eop = '1' AND stop_in = '0' THEN v.state := SET_STOP; - ELSIF q_reg.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND q_reg.stopped = '0' THEN + ELSIF q_reg.stop_adr = TO_UVEC(inp_adr, c_adr_w) THEN v.state := STOP_WRITING; - ELSE - v.state := WRITING; END IF; @@ -269,33 +273,21 @@ BEGIN v.dvr_mosi.wr := '1'; v.dvr_mosi.rd := '0'; - IF q_reg.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND q_reg.stopped = '0' THEN + IF q_reg.stop_adr = TO_UVEC(inp_adr, c_adr_w) THEN v.state := STOP_WRITING; ELSE v.state := WRITING; END IF; - WHEN STOP_WRITING => - -- this state stops the writing by generatign one last whole write burst which almost empties wr_fifo. + -- this state stops the writing by generating one last whole write burst which almost empties wr_fifo. v.wr_sosi.valid := '0'; v.dvr_mosi.burstbegin := '0'; v.stopped := '1'; v.stop_adr := TO_UVEC(g_max_adr, c_adr_w); - -- wait until the write burst is finished - IF inp_data_stopped = '0' THEN - v.state := STOP_WRITING; - ELSIF dvr_miso.done = '1' AND q_reg.dvr_mosi.burstbegin = '0' AND q_reg.wr_burst_en = '0' AND q_reg.wr_bursts_ready = 0 THEN - v.state := LAST_WRITE_BURST; - ELSE - v.state := STOP_WRITING; - END IF; - -- still receiving write data. - -- if adr mod g_burstsize = 0 - -- this makes sure that only ones every 64 writes a writeburst is started. v.wr_bursts_ready := TO_UINT(wr_fifo_usedw(g_wr_fifo_uw_w-1 DOWNTO c_bitshift_w)); IF NOT (q_reg.wr_bursts_ready = 0) AND q_reg.dvr_mosi.burstbegin = '0'THEN v.wr_burst_en := '1'; @@ -319,6 +311,10 @@ BEGIN v.dvr_mosi.wr := '1'; v.dvr_mosi.rd := '0'; + IF dvr_miso.done = '1' AND q_reg.dvr_mosi.burstbegin = '0' AND q_reg.wr_burst_en = '0' AND q_reg.wr_bursts_ready = 0 THEN + v.state := LAST_WRITE_BURST; + END IF; + WHEN LAST_WRITE_BURST => -- this state stops the writing by generatign one last write burst which empties wr_fifo. @@ -330,13 +326,11 @@ BEGIN v.rd_burst_en := '1'; ELSE v.dvr_mosi.burstbegin := '0'; - v.state := LAST_WRITE_BURST; END IF; v.dvr_mosi.wr := '1'; v.dvr_mosi.rd := '0'; - WHEN START_READING => -- this state generates the first read burst, the size of this burst is dependend on the size of the last write burst. v.dvr_mosi.burstbegin := '0'; @@ -356,8 +350,6 @@ BEGIN IF dvr_miso.done = '0' AND q_reg.rd_burst_en = '0' THEN v.rd_burst_en := '1'; v.state := READING; - ELSE - v.state := START_READING; END IF; @@ -389,66 +381,12 @@ BEGIN -- goes to STOP_reading when this read burst was from the burstblock before q_reg.stop_adr IF q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0) = TO_UVEC(q_reg.read_adr, c_adr_w) THEN v.state := STOP_READING; - ELSE - v.state := READING; END IF; - - WHEN STOP_READING => - -- this is the last read burst, this make sure every data containing word in the memory has been read. - IF TO_UINT(rd_fifo_usedw) <= g_burstsize AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN - v.dvr_mosi.burstbegin := '1'; - v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0); - v.dvr_mosi.burstsize := TO_UVEC(q_reg.stop_burstsize, dvr_mosi.burstsize'length); - v.stopped := '0'; - v.wr_sosi.valid := '0'; - v.state := WAIT_FOR_SOP; - v.wr_burst_en := '1'; - v.rst_ddrctrl_input := '1'; - ELSE - v.dvr_mosi.burstbegin := '0'; - v.state := STOP_READING; - END IF; - v.dvr_mosi.wr := '0'; - v.dvr_mosi.rd := '1'; - - IF dvr_miso.done = '0' THEN - v.rd_burst_en := '1'; - END IF; - - - - WHEN IDLE => - IF q_reg.started = '0' THEN - v.wr_sosi.valid := '0'; - END IF; - -- the statemachine goes to Idle when its finished or when its waiting on other components. - - WHEN OTHERS => - v := c_t_reg_init; - - END CASE; - IF q_reg.state = RESET OR q_reg.state = IDLE THEN - IF stop_in = '1' THEN - v.ready_for_set_stop := '1'; - ELSIF q_reg.ready_for_set_stop = '1' AND inp_sosi.eop = '1' THEN - v.state := SET_STOP; - ELSIF q_reg.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND q_reg.stopped = '0' THEN - v.state := STOP_WRITING; - ELSIF v.stopped = '0' AND inp_sosi.valid = '1' AND q_reg.started = '1' THEN - v.state := WRITING; - ELSIF q_reg.stopped = '1' THEN - v.state := STOP_READING; - ELSE - v.state := IDLE; - END IF; - END IF; - - IF rst = '1' THEN v.state := RESET; END IF; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd index f85f1b201e9f30497302d8b684c47f73647325c9..a385fc82c94e6ff7d84ff7c1446bf4b23912d55e 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input_repack.vhd @@ -108,25 +108,6 @@ BEGIN v.out_data_stopped := '0'; - - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*1) AND (v.out_data_count = '0') THEN - v.state := FIRST_OUTPUT; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*2) AND (v.out_data_count = '1') THEN - v.state := OVERFLOW_OUTPUT; - ELSE - v.state := FILL_VECTOR; - END IF; - - IF in_sosi.eop = '1' THEN - v.s_input_cnt := 0; - v.state := BSN; - END IF; - - WHEN FIRST_OUTPUT => -- if the input data exceeds output data vector width but not the c_v width v.c_v(g_in_data_w*(q_reg.c_v_count+1)+q_reg.out_of-1 DOWNTO g_in_data_w*q_reg.c_v_count+q_reg.out_of) := in_sosi.data(g_in_data_w-1 DOWNTO 0); -- fill c_v v.c_v_count := q_reg.c_v_count+1; -- increase the counter of c_v with 1 @@ -140,22 +121,6 @@ BEGIN v.out_data_stopped := '0'; - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*2) THEN - v.state := OVERFLOW_OUTPUT; - ELSE - v.state := FILL_VECTOR; - END IF; - - IF in_sosi.eop = '1' THEN - v.s_input_cnt := 0; - v.state := BSN; - END IF; - - WHEN OVERFLOW_OUTPUT => -- if the input data exceeds the output data vector width and the c_v width v.out_of := q_reg.out_of+(g_in_data_w*(q_reg.c_v_count+1))-(c_out_data_w*2); -- check how much overflow there is and safe it in out_of v.c_v(k_c_v_w-1 DOWNTO k_c_v_w-(g_in_data_w-v.out_of)) := in_sosi.data(g_in_data_w-v.out_of-1 DOWNTO 0); -- fill the rest of c_v untill the end @@ -171,22 +136,6 @@ BEGIN v.out_data_stopped := '0'; - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*1) THEN - v.state := FIRST_OUTPUT; - ELSE - v.state := FILL_VECTOR; - END IF; - - IF in_sosi.eop = '1' THEN - v.s_input_cnt := 0; - v.state := BSN; - END IF; - - WHEN BSN => v.c_v(k_c_v_w-1 DOWNTO ((g_in_data_w*q_reg.c_v_count)+q_reg.out_of)) := (OTHERS =>'0'); @@ -208,53 +157,36 @@ BEGIN v.out_sosi.eop := '1'; - - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*1) AND (v.out_data_count = '0') THEN - v.state := FIRST_OUTPUT; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*2) AND (v.out_data_count = '1') THEN - v.state := OVERFLOW_OUTPUT; - ELSE - v.state := FILL_VECTOR; - END IF; - - WHEN RESET => v := c_t_reg_init; v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := in_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0); - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSE - v.state := FILL_VECTOR; - END IF; - WHEN STOP => v.out_sosi.valid := '0'; v.q_sop := '0'; v.out_data_stopped := '1'; - IF rst = '1' THEN - v.state := RESET; - ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN - v.state := STOP; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*1) AND (v.out_data_count = '0') THEN - v.state := FIRST_OUTPUT; - ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*2) AND (v.out_data_count = '1') THEN - v.state := OVERFLOW_OUTPUT; - ELSE - v.state := FILL_VECTOR; - END IF; END CASE; + IF rst = '1' THEN + v.state := RESET; + ELSIF in_stop = '1' OR in_sosi.valid = '0' THEN + v.state := STOP; + ELSIF in_sosi.eop = '1' THEN + v.s_input_cnt := 0; + v.state := BSN; + ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*1) AND (v.out_data_count = '0') THEN + v.state := FIRST_OUTPUT; + ELSIF ((g_in_data_w*(v.c_v_count+1))+v.out_of >= c_out_data_w*2) AND (v.out_data_count = '1') THEN + v.state := OVERFLOW_OUTPUT; + ELSE + v.state := FILL_VECTOR; + END IF; + + d_reg <= v; END PROCESS; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd index d49c47a082d2a9ab29159ca12447af8aafc7a88d..0c38238cf32190098ee91ee7f27916fb9c9e0245 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd @@ -97,41 +97,17 @@ BEGIN BEGIN - v := q_reg; + v := q_reg; IF out_siso.ready = '1' OR q_reg.state = OFF OR q_reg.state = IDLE OR q_reg.state = RESET OR rst = '1' THEN CASE q_reg.state IS WHEN READING => -- generating output from the data already present in c_v - v.out_ready := '0'; v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); - v.out_sosi.valid := '1'; - v.bsn_cnt := q_reg.bsn_cnt+1; - v.op_data_cnt := q_reg.op_data_cnt+1; - - IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.valid_data := '1'; - END IF; - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - - IF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN - v.state := OVER_HALF; - ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '0' AND v.valid_data = '0' THEN - v.state := IDLE; - ELSIF out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; - - + v.out_sosi.valid := '1'; + v.bsn_cnt := q_reg.bsn_cnt+1; + v.op_data_cnt := q_reg.op_data_cnt+1; + IF q_reg.out_sosi.eop = '1' THEN v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := INCR_UVEC(q_reg.out_sosi.bsn, 1); v.out_sosi.eop := '0'; @@ -140,285 +116,130 @@ BEGIN ELSIF q_reg.out_sosi.sop = '1' THEN v.out_sosi.sop := '0'; END IF; - - IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN - v.state := BSN; - v.out_ready := '1'; - ELSIF q_reg.bsn_cnt = g_block_size-3 THEN - v.state := IDLE; - END IF; - - - + + WHEN OVER_HALF => -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added - IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN - v.out_ready := '1'; - -- generate output from the middle of c_v - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); - v.out_sosi.valid := '1'; - v.bsn_cnt := q_reg.bsn_cnt+1; - -- put the second half of c_v into the first half of c_v - v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - -- put the delay data into the first half of c_v - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.a_of := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w; - v.op_data_cnt := 0; - ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN - v.out_ready := '1'; + IF q_reg.valid_data = '1' THEN -- generate output from the middle of c_v v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); v.out_sosi.valid := '1'; v.bsn_cnt := q_reg.bsn_cnt+1; -- put the second half of c_v into the first half of c_v v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - -- put zeros into the second half of c_v beceause dd_fresh is '0' - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0'); - v.a_of := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w; - v.op_data_cnt := 0; v.valid_data := '0'; - ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN - v.out_ready := '1'; - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - -- generate output from the middle of c_v - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); - -- put the second half of c_v into the first half of c_v - v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - v.out_sosi.valid := '1'; - v.bsn_cnt := q_reg.bsn_cnt+1; - v.dd_fresh := '0'; v.a_of := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w; v.op_data_cnt := 0; + ELSIF q_reg.valid_data = '0' THEN + -- there is no data ready. END IF; - - - - - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - IF (g_out_data_w*(v.op_data_cnt+1))+v.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN - v.state := OVER_HALF; - ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' THEN - v.state := IDLE; - ELSIF out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; - + IF q_reg.out_sosi.sop = '1' THEN v.out_sosi.sop := '0'; END IF; - - IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN - v.state := BSN; - v.dd_fresh := '1'; - ELSIF q_reg.bsn_cnt = g_block_size-3 THEN - v.state := IDLE; - END IF; - - + + WHEN FIRST_READ => + -- put the second half of c_v into the first half of c_v + v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); + v.valid_data := '0'; + -- fills the first half of c_v and generates output from it. - v.out_ready := '1'; - v.c_v(c_v_w-1 DOWNTO 0) := (OTHERS => '0'); - v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v(g_out_data_w+v.a_of-1 DOWNTO v.a_of); + v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); + v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v(g_out_data_w-1 DOWNTO 0); v.out_sosi.valid := '1'; v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := in_bsn(c_dp_stream_bsn_w-1 DOWNTO 0); v.out_sosi.sop := '1'; v.out_sosi.eop := '0'; v.bsn_cnt := 0; - v.op_data_cnt := q_reg.op_data_cnt+1; - - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - IF out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; - + v.op_data_cnt := 1; + + WHEN BSN => -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added also increases the bsn output v.out_sosi.valid := '0'; - IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN - -- generate output from the middle of c_v - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); - v.out_sosi.valid := '1'; - v.bsn_cnt := q_reg.bsn_cnt+1; - -- put the second half of c_v into the first half of c_v - v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - -- put the delay data into the first half of c_v - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.op_data_cnt := 0; - ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN + IF q_reg.valid_data = '1' THEN -- generate output from the middle of c_v v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); v.out_sosi.valid := '1'; v.bsn_cnt := q_reg.bsn_cnt+1; -- put the second half of c_v into the first half of c_v v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - -- put zeros into the second half of c_v beceause dd_fresh is '0' - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0'); - v.op_data_cnt := 0; v.valid_data := '0'; - ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - -- generate output from the middle of c_v - v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); - -- put the second half of c_v into the first half of c_v - v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w); - v.out_sosi.valid := '1'; - v.bsn_cnt := q_reg.bsn_cnt+1; - v.dd_fresh := '0'; v.op_data_cnt := 0; - ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w THEN + ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w THEN -- generate output from the middle of c_v v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); v.out_sosi.valid := '1'; v.bsn_cnt := q_reg.bsn_cnt+1; END IF; - - v.out_ready := '0'; + v.out_sosi.eop := '1'; v.a_of := 0; v.bsn_cnt := q_reg.bsn_cnt+1; - - IF v.dd_fresh = '1' AND v.valid_data = '0' THEN - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.valid_data := '1'; - END IF; - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - IF g_bim+TO_UINT(in_bsn)-1 = TO_UINT(v.out_sosi.bsn) THEN - v.state := RESET; - ELSIF out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; - + + WHEN RESET => v := c_t_reg_init; - - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - v.state := OFF; - - + + WHEN IDLE => -- the statemachine goes to Idle when its finished or when its waiting on other components. - IF q_reg.dd_fresh = '0' THEN - v.out_ready := '1'; - ELSE - v.out_ready := '0'; - END IF; v.out_sosi.valid := '0'; - - IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.valid_data := '1'; - END IF; - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - - IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '0' THEN - v.state := IDLE; - ELSIF q_reg.bsn_cnt = g_block_size-3 THEN - v.state := BSN; - ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '1' AND out_siso.ready = '1' AND out_siso.ready = '1' THEN - v.state := OVER_HALF; - ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w AND out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; - - - + + WHEN OFF => -- the stamachine has a state off so it knows when to go to first read, it can't go to first read from IDLE v.out_sosi := c_dp_sosi_init; v.bsn_cnt := 0; v.state_off := '1'; - - IF in_sosi.valid = '1' AND q_reg.dd_fresh = '0' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - v.out_ready := '0'; - v.state_off := '0'; - v.state := FIRST_READ; - ELSIF q_reg.dd_fresh = '1' THEN - v.out_ready := '0'; - v.state := OFF; - ELSIF out_siso.ready = '1' THEN - v.out_ready := '1'; - v.state := OFF; - ELSE - v.state := OFF; - END IF; - - + + END CASE; + + ELSE - IF q_reg.dd_fresh = '0' THEN - v.out_ready := '1'; - ELSE - v.out_ready := '0'; - END IF; - v.out_sosi.valid := '0'; - - IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN - -- put the delay data into the second half of c_v beceause these are now zeros - v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '0'; - v.valid_data := '1'; - END IF; - IF in_sosi.valid = '1' THEN - v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); - v.dd_fresh := '1'; - END IF; - - - IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '0' THEN - v.state := IDLE; - ELSIF q_reg.bsn_cnt = g_block_size-3 THEN - v.state := BSN; - ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '1' AND out_siso.ready = '1' AND out_siso.ready = '1' THEN - v.state := OVER_HALF; - ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w AND out_siso.ready = '1' THEN - v.state := READING; - ELSE - v.state := IDLE; - END IF; + -- IDLE + v.out_sosi.valid := '0'; END IF; + + -- compensating for fifo delay + IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN + -- put the delay data into the second half of c_v beceause these are now zeros + v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0); + v.dd_fresh := '0'; + v.valid_data := '1'; + END IF; + IF in_sosi.valid = '1' THEN + v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0); + v.dd_fresh := '1'; + END IF; + + IF rst = '1' THEN - v.state := RESET; + v.state := RESET; + ELSIF q_reg.state = RESET OR (q_reg.valid_data = '0' AND q_reg.state = OFF) OR (((g_bim+TO_UINT(in_bsn)-1) = TO_UINT(q_reg.out_sosi.bsn)) AND v.out_sosi.eop = '1') THEN + v.state := OFF; + ELSIF q_reg.state = OFF THEN + v.state_off := '0'; + v.state := FIRST_READ; + ELSIF out_siso.ready = '0' THEN + v.state := IDLE; + ELSIF q_reg.bsn_cnt = g_block_size-3 THEN + v.state := BSN; + ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' THEN + v.state := IDLE; + ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w THEN + v.state := OVER_HALF; + ELSE + v.state := READING; + END IF; + + IF q_reg.state = OFF AND in_sosi.valid = '1' THEN + v.out_ready := '0'; + ELSE + v.out_ready := NOT v.valid_data; END IF; d_reg <= v; END PROCESS;