From 980f483f95c16170804ac367d197bd555e6414ec Mon Sep 17 00:00:00 2001 From: JobvanWee <wee@astron.nl> Date: Wed, 8 Jun 2022 14:17:49 +0200 Subject: [PATCH] Removed _sosi. --- .../lofar2/designs/lofar2_unb2c_ddrctrl/_sosi | 439 ------------------ .../libraries/ddrctrl/src/vhdl/ddrctrl.vhd | 1 + .../ddrctrl/src/vhdl/ddrctrl_controller.vhd | 66 ++- .../base/common/src/vhdl/common_fifo_dc.vhd | 3 + libraries/base/dp/src/vhdl/dp_fifo_core.vhd | 4 +- 5 files changed, 52 insertions(+), 461 deletions(-) delete mode 100644 applications/lofar2/designs/lofar2_unb2c_ddrctrl/_sosi diff --git a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/_sosi b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/_sosi deleted file mode 100644 index fbddc8f71c..0000000000 --- a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/_sosi +++ /dev/null @@ -1,439 +0,0 @@ -------------------------------------------------------------------------------- --- --- Copyright 2022 --- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> --- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- -------------------------------------------------------------------------------- --- Author: Job van Wee --- Purpose: controller for ddrctrl, decides when to write when to read or when to stop writing or reading. --- --- Description: --- --- Remark: --- Use VHDL coding template from: --- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding --- - -LIBRARY IEEE, dp_lib, common_lib, tech_ddr_lib; -USE IEEE.std_logic_1164.ALL; -USE IEEE.numeric_std.ALL; -USE dp_lib.dp_stream_pkg.ALL; -USE common_lib.common_mem_pkg.ALL; -USE common_lib.common_pkg.ALL; -USE tech_ddr_lib.tech_ddr_pkg.ALL; - - -ENTITY ddrctrl_controller IS - GENERIC ( - g_tech_ddr : t_c_tech_ddr; - g_stop_percentage : NATURAL := 50; - g_nof_streams : NATURAL; -- 12 - g_out_data_w : NATURAL; -- 14 - g_wr_data_w : NATURAL; -- 168 - g_rd_fifo_depth : NATURAL; -- 256 - g_rd_data_w : NATURAL; -- 256 - g_block_size : NATURAL; -- 1024 - g_wr_fifo_uw_w : NATURAL; -- 8 - g_rd_fifo_uw_w : NATURAL; -- 8 - g_max_adr : NATURAL; -- 16128 - g_burstsize : NATURAL; -- 64 - g_last_burstsize : NATURAL; -- 18 - g_adr_per_b : NATURAL; -- 299 - g_bim : NATURAL -- 54 - ); - PORT ( - clk : IN STD_LOGIC; - rst : IN STD_LOGIC; - - -- ddrctrl_input - inp_of : IN NATURAL; - inp_sosi : IN t_dp_sosi; - inp_adr : IN NATURAL; - inp_bsn_adr : IN NATURAL; - inp_data_stopped : IN STD_LOGIC; - rst_ddrctrl_input_ac : OUT STD_LOGIC; - - -- io_ddr - dvr_mosi : OUT t_mem_ctlr_mosi; - dvr_miso : IN t_mem_ctlr_miso; - wr_sosi : OUT t_dp_sosi; - wr_fifo_usedw : IN STD_LOGIC_VECTOR(g_wr_fifo_uw_w-1 DOWNTO 0); - rd_fifo_usedw : IN STD_LOGIC_VECTOR(g_rd_fifo_uw_w-1 DOWNTO 0); - - -- ddrctrl_output - outp_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); - - -- ddrctrl_controller - stop_in : IN STD_LOGIC; - stop_out : OUT STD_LOGIC; - ddrctrl_ctrl_state : OUT STD_LOGIC_VECTOR(32-1 DOWNTO 0) := (OTHERS => '0') - ); -END ddrctrl_controller; - -ARCHITECTURE rtl OF ddrctrl_controller IS - - CONSTANT c_bitshift_w : NATURAL := ceil_log2(g_burstsize); -- bitshift to make sure there is only a burst start at a interval of c_burstsize. - CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27 - CONSTANT c_pof_ma : NATURAL := (((g_max_adr*(100-g_stop_percentage))/100)/g_adr_per_b)*g_adr_per_b; --percentage of max address. - - CONSTANT c_zeros : STD_LOGIC_VECTOR(c_bitshift_w-1 DOWNTO 0) := (OTHERS => '0'); - - -- constant for reading - - - CONSTANT c_rd_data_w : NATURAL := g_nof_streams*g_out_data_w; -- 168 - CONSTANT c_rest : NATURAL := c_rd_data_w-(g_wr_data_w mod c_rd_data_w); -- 96 - 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, STOP_READING, WAIT_FOR_SOP, WRITING, SET_STOP, STOP_WRITING, LAST_WRITE_BURST, START_READING, READING); - - -- record for readability - TYPE t_reg IS RECORD - -- state of program - state : t_state; - started : STD_LOGIC; - - -- stopping signals - ready_for_set_stop : STD_LOGIC; - stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); - last_adr_to_write_to : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); - stop_burstsize : NATURAL; - stopped : STD_LOGIC; - rst_ddrctrl_input_ac : STD_LOGIC; - - -- writing signals - wr_burst_en : STD_LOGIC; - wr_bursts_ready : NATURAL; - - -- reading signals - outp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); - read_adr : NATURAL; - rd_burst_en : STD_LOGIC; - - -- output - dvr_mosi : t_mem_ctlr_mosi; - wr_sosi : t_dp_sosi; - ddrctrl_ctrl_state : STD_LOGIC_VECTOR(32-1 DOWNTO 0); - 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, '1', c_mem_ctlr_mosi_rst, c_dp_sosi_init, (OTHERS => '0')); - - - -- signals for readability - SIGNAL d_reg : t_reg := c_t_reg_init; - SIGNAL q_reg : t_reg := c_t_reg_init; - - -BEGIN - - q_reg <= d_reg WHEN rising_edge(clk); - - -- put the input data into c_v and fill the output vector from c_v - p_state : PROCESS(q_reg, rst, inp_of, inp_sosi, inp_adr, inp_bsn_adr, inp_data_stopped, dvr_miso, rd_fifo_usedw, wr_fifo_usedw, stop_in) - - VARIABLE v : t_reg := c_t_reg_init; - - BEGIN - - v := q_reg; - v.wr_sosi := inp_sosi; - - - CASE q_reg.state IS - WHEN RESET => - v := c_t_reg_init; - v.dvr_mosi.burstbegin := '1'; - v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); - v.dvr_mosi.wr := '1'; - v.wr_sosi.valid := '1'; - - IF rst = '0' THEN - v.state := STOP_READING; - END IF; - - - WHEN STOP_READING => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(1, 32); - -- 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_ac := '1'; - ELSE - v.dvr_mosi.burstbegin := '0'; - 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 WAIT_FOR_SOP => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(2, 32); - v.dvr_mosi.burstbegin := '0'; - v.rst_ddrctrl_input_ac := '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 => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(3, 32); - -- this state generates the rest of the write bursts, it also checks if there is a stop signal or if it needs to stop writing. - v.wr_bursts_ready := TO_UINT(wr_fifo_usedw(g_wr_fifo_uw_w-1 DOWNTO c_bitshift_w)); - IF q_reg.wr_bursts_ready >= 1 AND dvr_miso.done = '1' AND q_reg.wr_burst_en = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN - v.dvr_mosi.burstbegin := '1'; - v.wr_burst_en := '0'; - IF inp_adr < (g_burstsize*q_reg.wr_bursts_ready)-1 THEN - v.dvr_mosi.address := TO_UVEC(g_max_adr-g_last_burstsize-(g_burstsize*(q_reg.wr_bursts_ready-1)), dvr_mosi.address'length); - v.dvr_mosi.burstsize := TO_UVEC(g_last_burstsize, dvr_mosi.burstsize'length); - ELSE - v.dvr_mosi.address := TO_UVEC(inp_adr-(g_burstsize*q_reg.wr_bursts_ready), dvr_mosi.address'length); - v.dvr_mosi.address(c_bitshift_w-1 DOWNTO 0) := c_zeros(c_bitshift_w-1 DOWNTO 0); -- makes sure that a burst is only started on a multiple of g_burstsize - v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - END IF; - ELSE - v.dvr_mosi.burstbegin := '0'; - END IF; - v.dvr_mosi.wr := '1'; - v.dvr_mosi.rd := '0'; - - IF NOT (q_reg.wr_bursts_ready = 0) AND q_reg.dvr_mosi.burstbegin = '0'THEN - v.wr_burst_en := '1'; - ELSIF q_reg.wr_bursts_ready = 0 THEN - v.wr_burst_en := '0'; - END IF; - - IF stop_in = '1' THEN - v.ready_for_set_stop := '1'; - END IF; - - 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) THEN - v.state := STOP_WRITING; - END IF; - - - WHEN SET_STOP => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(4, 32); - -- this state sets a stop address dependend on the g_stop_percentage. - IF inp_adr-c_pof_ma >= 0 THEN - v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr-c_pof_ma, c_adr_w); - ELSE - v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr+g_max_adr-c_pof_ma, c_adr_w); - END IF; - v.ready_for_set_stop := '0'; - IF TO_UINT(v.stop_adr(c_adr_w-1 DOWNTO 0)) = 0 THEN - v.last_adr_to_write_to(c_adr_w-1 DOWNTO 0) := TO_UVEC(g_max_adr-g_last_burstsize, c_adr_w); - ELSE - v.last_adr_to_write_to(c_adr_w-1 DOWNTO c_bitshift_w) := v.stop_adr(c_adr_w-1 DOWNTO c_bitshift_w); - END IF; - v.last_adr_to_write_to(c_bitshift_w-1 DOWNTO 0) := (OTHERS => '0'); - v.stop_burstsize := TO_UINT(v.stop_adr(c_adr_w-1 DOWNTO 0))-TO_UINT(v.last_adr_to_write_to)+1; - - -- still a write cyle - -- 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'; - ELSIF q_reg.wr_bursts_ready = 0 THEN - v.wr_burst_en := '0'; - END IF; - IF dvr_miso.done = '1' AND q_reg.wr_burst_en = '1' THEN - v.dvr_mosi.burstbegin := '1'; - v.wr_burst_en := '0'; - IF inp_adr < (g_burstsize*q_reg.wr_bursts_ready)-1 THEN - v.dvr_mosi.address := TO_UVEC(g_max_adr-g_last_burstsize-(g_burstsize*(q_reg.wr_bursts_ready-1)), dvr_mosi.address'length); - v.dvr_mosi.burstsize := TO_UVEC(g_last_burstsize, dvr_mosi.burstsize'length); - ELSE - v.dvr_mosi.address := TO_UVEC(inp_adr-(g_burstsize*q_reg.wr_bursts_ready), dvr_mosi.address'length); - v.dvr_mosi.address(c_bitshift_w-1 DOWNTO 0) := c_zeros(c_bitshift_w-1 DOWNTO 0); -- makes sure that a burst is only started on a multiple of g_burstsize - v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - END IF; - ELSE - v.dvr_mosi.burstbegin := '0'; - END IF; - v.dvr_mosi.wr := '1'; - v.dvr_mosi.rd := '0'; - - 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 => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(5, 32); - -- 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); - - -- still receiving write data. - 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'; - ELSIF q_reg.wr_bursts_ready = 0 THEN - v.wr_burst_en := '0'; - END IF; - IF dvr_miso.done = '1' AND q_reg.wr_burst_en = '1' THEN - v.dvr_mosi.burstbegin := '1'; - v.wr_burst_en := '0'; - IF inp_adr < (g_burstsize*q_reg.wr_bursts_ready)-1 THEN - v.dvr_mosi.address := TO_UVEC(g_max_adr-g_last_burstsize-(g_burstsize*q_reg.wr_bursts_ready-1), dvr_mosi.address'length); - v.dvr_mosi.burstsize := TO_UVEC(g_last_burstsize, dvr_mosi.burstsize'length); - ELSE - v.dvr_mosi.address := TO_UVEC(inp_adr-(g_burstsize*q_reg.wr_bursts_ready), dvr_mosi.address'length); - v.dvr_mosi.address(c_bitshift_w-1 DOWNTO 0) := c_zeros(c_bitshift_w-1 DOWNTO 0); -- makes sure that a burst is only started on a multiple of g_burstsize - v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - END IF; - ELSE - v.dvr_mosi.burstbegin := '0'; - END IF; - 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 => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(6, 32); - -- this state stops the writing by generatign one last write burst which empties wr_fifo. - v.wr_sosi.valid := '0'; - IF dvr_miso.done = '1' THEN - IF TO_UINT(q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0)) >= g_max_adr THEN - v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(0, c_adr_w); - v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - ELSE - 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); - END IF; - v.dvr_mosi.burstbegin := '1'; - v.state := START_READING; - v.rd_burst_en := '1'; - ELSE - v.dvr_mosi.burstbegin := '0'; - END IF; - v.dvr_mosi.wr := '1'; - v.dvr_mosi.rd := '0'; - - - WHEN START_READING => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(7, 32); - -- 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'; - v.outp_bsn := TO_UVEC(TO_UINT(inp_sosi.bsn)-g_bim, c_dp_stream_bsn_w); - v.wr_sosi.valid := '0'; - - IF dvr_miso.done = '1' AND v.rd_burst_en = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN - IF TO_UINT(q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0))+q_reg.stop_burstsize >= g_max_adr THEN - v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(0, c_adr_w); - v.read_adr := g_burstsize; - ELSE - v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := TO_UVEC(g_burstsize-q_reg.stop_burstsize, dvr_mosi.burstsize'length); - 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.read_adr := TO_UINT(q_reg.last_adr_to_write_to(c_adr_w-1 DOWNTO 0))+g_burstsize; - END IF; - v.dvr_mosi.burstbegin := '1'; - v.dvr_mosi.wr := '0'; - v.dvr_mosi.rd := '1'; - v.rd_burst_en := '0'; - END IF; - - -- makes sure the fifo is filled before asking for another rd request. to prevent 4 rd burst to happend directly after one another. - IF dvr_miso.done = '0' AND q_reg.rd_burst_en = '0' THEN - v.rd_burst_en := '1'; - v.state := READING; - END IF; - - - WHEN READING => - v.ddrctrl_ctrl_state(32-1 DOWNTO 0) := TO_UVEC(8, 32); - v.wr_sosi.valid := '0'; - -- rd_fifo needs a refil after rd_fifo_usedw <= 10 because of delays, if you wait until rd_fifo_usedw = 0 then you get an empty fifo which results in your outputs sosi.valid not being constatly valid. - IF TO_UINT(rd_fifo_usedw) <= g_burstsize AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN - v.dvr_mosi.wr := '0'; - v.dvr_mosi.rd := '1'; - v.dvr_mosi.burstbegin := '1'; - v.rd_burst_en := '0'; - IF q_reg.read_adr > g_max_adr-g_burstsize THEN - v.dvr_mosi.address := TO_UVEC(q_reg.read_adr, dvr_mosi.address'length); - v.dvr_mosi.burstsize := TO_UVEC(g_last_burstsize, dvr_mosi.burstsize'length); - v.read_adr := 0; - ELSE - v.dvr_mosi.address := TO_UVEC(q_reg.read_adr, dvr_mosi.address'length); - v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length); - v.read_adr := q_reg.read_adr+g_burstsize; - END IF; - ELSE - v.dvr_mosi.burstbegin := '0'; - END IF; - - -- makes sure the fifo is filled before asking for another rd request. to prevent 4 rd burst to happend directly after one another. - IF dvr_miso.done = '0' THEN - v.rd_burst_en := '1'; - END IF; - - -- 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; - END IF; - - - END CASE; - - - IF rst = '1' THEN - v.state := RESET; - END IF; - - IF inp_sosi.eop = '1' THEN - v.started := '1'; - END IF; - - d_reg <= v; - - END PROCESS; - - -- fill outputs - dvr_mosi <= q_reg.dvr_mosi; - wr_sosi <= q_reg.wr_sosi; - stop_out <= q_reg.stopped; - outp_bsn <= q_reg.outp_bsn; - rst_ddrctrl_input_ac <= q_reg.rst_ddrctrl_input_ac OR rst; - ddrctrl_ctrl_state <= q_reg.ddrctrl_ctrl_state; - - -END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 4b791b7b87..9eac3c7708 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -312,6 +312,7 @@ BEGIN wr_fifo_usedw => wr_fifo_usedw, rd_fifo_usedw => rd_fifo_usedw, ctlr_wr_flush_en => ctlr_wr_flush_en, + flush_state => state_vec, -- ddrctrl_output outp_bsn => bsn_co, diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd index 5c1b1b4de3..3a3591aba1 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd @@ -70,9 +70,11 @@ ENTITY ddrctrl_controller IS dvr_mosi : OUT t_mem_ctlr_mosi; dvr_miso : IN t_mem_ctlr_miso; wr_sosi : OUT t_dp_sosi; + wr_siso : IN t_dp_siso; wr_fifo_usedw : IN STD_LOGIC_VECTOR(g_wr_fifo_uw_w-1 DOWNTO 0); rd_fifo_usedw : IN STD_LOGIC_VECTOR(g_rd_fifo_uw_w-1 DOWNTO 0); ctlr_wr_flush_en : IN STD_LOGIC; + flush_state : IN STD_LOGIC_VECTOR(1 DOWNTO 0); -- ddrctrl_output outp_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); @@ -121,7 +123,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS CONSTANT c_bre_ndx_w : NATURAL := c_high_bre_ndx-c_low_bre_ndx+1; -- type for statemachine - TYPE t_state IS (RESET, STOP_READING, WAIT_FOR_SOP, WRITING, SET_STOP, STOP_WRITING, LAST_WRITE_BURST, START_READING, READING); + TYPE t_state IS (RESET, STOP_FLUSH, STOP_READING, WAIT_FOR_SOP, WRITING, SET_STOP, STOP_WRITING, LAST_WRITE_BURST, START_READING, READING); -- record for readability TYPE t_reg IS RECORD @@ -129,6 +131,9 @@ ARCHITECTURE rtl OF ddrctrl_controller IS state : t_state; started : STD_LOGIC; + -- stopping flush + timer : NATURAL; + -- stopping signals ready_for_set_stop : STD_LOGIC; stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); @@ -152,7 +157,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS ddrctrl_ctrl_state : STD_LOGIC_VECTOR(32-1 DOWNTO 0); 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, '1', c_mem_ctlr_mosi_rst, c_dp_sosi_init, (OTHERS => '0')); + CONSTANT c_t_reg_init : t_reg := (RESET, '0', 4, '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, (OTHERS => '0')); -- signals for readability @@ -173,32 +178,51 @@ BEGIN v := q_reg; v.wr_sosi := inp_sosi; - v.ddrctrl_ctrl_state(c_high_bsn_ndx DOWNTO c_low_bsn_ndx) := inp_sosi.bsn(c_start_bsn+c_bsn_ndx_w-1 DOWNTO c_start_bsn); - v.ddrctrl_ctrl_state(c_high_adr_ndx DOWNTO c_low_adr_ndx) := TO_UVEC(inp_adr, 32)(c_adr_ndx_w-1 DOWNTO 0); + --v.ddrctrl_ctrl_state(c_high_bsn_ndx DOWNTO c_low_bsn_ndx) := inp_sosi.bsn(c_start_bsn+c_bsn_ndx_w-1 DOWNTO c_start_bsn); + --v.ddrctrl_ctrl_state(c_high_adr_ndx DOWNTO c_low_adr_ndx) := TO_UVEC(inp_adr, 32)(c_adr_ndx_w-1 DOWNTO 0); CASE q_reg.state IS WHEN RESET => v := c_t_reg_init; - v.dvr_mosi.burstbegin := '1'; - v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); - v.dvr_mosi.wr := '1'; - v.wr_sosi.valid := '1'; v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(0, c_state_ndx_w); - IF rst = '0' THEN - v.state := STOP_READING; + IF rst = '0' AND wr_siso.ready = '1' THEN + v.state := STOP_FLUSH; + v.timer := 0; + END IF; + + + WHEN STOP_FLUSH => + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(1, c_state_ndx_w); + v.wr_sosi.valid := '0'; + IF flush_state = "10" THEN + v.dvr_mosi.burstbegin := '1'; + v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); + v.dvr_mosi.wr := '1'; + ELSIF flush_state = "11" AND q_reg.timer = 0 THEN + v.wr_sosi.valid := '1'; + v.timer := 127; + END IF; + + IF q_reg.timer > 0 AND rst = '0' THEN + v.timer := q_reg.timer-1; + END IF; + + IF flush_state = "01" THEN + v.state := WAIT_FOR_SOP; + v.stopped := '0'; END IF; WHEN STOP_READING => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(1, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(2, c_state_ndx_w); -- 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.wr_sosi.valid := '1'; v.state := WAIT_FOR_SOP; v.wr_burst_en := '1'; v.rst_ddrctrl_input_ac := '1'; @@ -214,14 +238,14 @@ BEGIN WHEN WAIT_FOR_SOP => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(2, c_state_ndx_w); - v.dvr_mosi.burstbegin := '1'; + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(3, c_state_ndx_w); + v.dvr_mosi.burstbegin := '0'; v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); v.dvr_mosi.wr := '1'; v.dvr_mosi.rd := '0'; v.rst_ddrctrl_input_ac := '0'; IF q_reg.started = '0' AND inp_sosi.eop = '1' THEN - v.wr_sosi.valid := '1'; + v.wr_sosi.valid := '0'; ELSIF inp_sosi.sop = '1' THEN v.state := WRITING; ELSE @@ -230,7 +254,7 @@ BEGIN WHEN WRITING => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(3, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(4, c_state_ndx_w); -- this state generates the rest of the write bursts, it also checks if there is a stop signal or if it needs to stop writing. v.wr_bursts_ready := TO_UINT(wr_fifo_usedw(g_wr_fifo_uw_w-1 DOWNTO c_bitshift_w)); IF q_reg.wr_bursts_ready >= 1 AND dvr_miso.done = '1' AND q_reg.wr_burst_en = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN @@ -268,7 +292,7 @@ BEGIN WHEN SET_STOP => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(4, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(5, c_state_ndx_w); -- this state sets a stop address dependend on the g_stop_percentage. IF inp_adr-c_pof_ma >= 0 THEN v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr-c_pof_ma, c_adr_w); @@ -318,7 +342,7 @@ BEGIN WHEN STOP_WRITING => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(5, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(6, c_state_ndx_w); -- 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'; @@ -355,7 +379,7 @@ BEGIN WHEN LAST_WRITE_BURST => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(6, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(7, c_state_ndx_w); -- this state stops the writing by generatign one last write burst which empties wr_fifo. v.wr_sosi.valid := '0'; IF dvr_miso.done = '1' THEN @@ -377,7 +401,7 @@ BEGIN WHEN START_READING => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(7, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(8, c_state_ndx_w); -- 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'; v.outp_bsn := INCR_UVEC(inp_sosi.bsn,-1*g_bim); @@ -407,7 +431,7 @@ BEGIN WHEN READING => - v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(8, c_state_ndx_w); + v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(9, c_state_ndx_w); v.wr_sosi.valid := '0'; -- rd_fifo needs a refil after rd_fifo_usedw <= 10 because of delays, if you wait until rd_fifo_usedw = 0 then you get an empty fifo which results in your outputs sosi.valid not being constatly valid. IF TO_UINT(rd_fifo_usedw) <= g_burstsize AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN diff --git a/libraries/base/common/src/vhdl/common_fifo_dc.vhd b/libraries/base/common/src/vhdl/common_fifo_dc.vhd index 67242f2b23..8d0a2c3eec 100644 --- a/libraries/base/common/src/vhdl/common_fifo_dc.vhd +++ b/libraries/base/common/src/vhdl/common_fifo_dc.vhd @@ -39,6 +39,7 @@ ENTITY common_fifo_dc IS wr_clk : IN STD_LOGIC; wr_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); wr_req : IN STD_LOGIC; + wr_init_out : OUT STD_LOGIC; wr_ful : OUT STD_LOGIC; wrusedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_nof_words)-1 DOWNTO 0); rd_clk : IN STD_LOGIC; @@ -98,6 +99,8 @@ BEGIN out_rst => wr_init -- assume init has finished g_delay_len cycles after release of wr_rst ); + wr_init_out <= wr_init; + -- The FIFO under read and over write protection are kept enabled in the MegaWizard wr_en <= wr_req AND NOT wr_init; -- check on NOT ful is not necessary when overflow_checking="ON" (Altera) or according to fifo_generator_ug175.pdf (Xilinx) rd_en <= rd_req; -- check on NOT emp is not necessary when underflow_checking="ON" (Altera) diff --git a/libraries/base/dp/src/vhdl/dp_fifo_core.vhd b/libraries/base/dp/src/vhdl/dp_fifo_core.vhd index 8c7be411f7..083fd11c10 100644 --- a/libraries/base/dp/src/vhdl/dp_fifo_core.vhd +++ b/libraries/base/dp/src/vhdl/dp_fifo_core.vhd @@ -111,6 +111,7 @@ ARCHITECTURE str OF dp_fifo_core IS SIGNAL fifo_wr_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0); SIGNAL fifo_wr_req : STD_LOGIC; SIGNAL fifo_wr_ful : STD_LOGIC; + SIGNAL wr_init : STD_LOGIC := '0'; SIGNAL fifo_wr_usedw : STD_LOGIC_VECTOR(wr_usedw'RANGE); SIGNAL fifo_rd_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); @@ -166,7 +167,7 @@ BEGIN nxt_snk_out.xon <= src_in.xon; -- up stream use fifo almost full to control snk_out.ready - nxt_snk_out.ready <= '1' WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0'; + nxt_snk_out.ready <= NOT wr_init WHEN UNSIGNED(fifo_wr_usedw)<c_fifo_almost_full ELSE '0'; gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE u_common_fifo_sc : ENTITY common_lib.common_fifo_sc @@ -205,6 +206,7 @@ BEGIN wr_clk => wr_clk, wr_dat => fifo_wr_dat, wr_req => fifo_wr_req, + wr_init_out => wr_init, wr_ful => fifo_wr_ful, wrusedw => fifo_wr_usedw, rd_clk => rd_clk, -- GitLab