Skip to content
Snippets Groups Projects
Commit 980f483f authored by Job van Wee's avatar Job van Wee
Browse files

Removed _sosi.

parent 7bbeb9b4
Branches
No related tags found
1 merge request!260Resolve L2SDP-756
Pipeline #31458 passed
-------------------------------------------------------------------------------
--
-- 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;
...@@ -312,6 +312,7 @@ BEGIN ...@@ -312,6 +312,7 @@ BEGIN
wr_fifo_usedw => wr_fifo_usedw, wr_fifo_usedw => wr_fifo_usedw,
rd_fifo_usedw => rd_fifo_usedw, rd_fifo_usedw => rd_fifo_usedw,
ctlr_wr_flush_en => ctlr_wr_flush_en, ctlr_wr_flush_en => ctlr_wr_flush_en,
flush_state => state_vec,
-- ddrctrl_output -- ddrctrl_output
outp_bsn => bsn_co, outp_bsn => bsn_co,
......
...@@ -70,9 +70,11 @@ ENTITY ddrctrl_controller IS ...@@ -70,9 +70,11 @@ ENTITY ddrctrl_controller IS
dvr_mosi : OUT t_mem_ctlr_mosi; dvr_mosi : OUT t_mem_ctlr_mosi;
dvr_miso : IN t_mem_ctlr_miso; dvr_miso : IN t_mem_ctlr_miso;
wr_sosi : OUT t_dp_sosi; 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); 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); rd_fifo_usedw : IN STD_LOGIC_VECTOR(g_rd_fifo_uw_w-1 DOWNTO 0);
ctlr_wr_flush_en : IN STD_LOGIC; ctlr_wr_flush_en : IN STD_LOGIC;
flush_state : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
-- ddrctrl_output -- ddrctrl_output
outp_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); 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 ...@@ -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; CONSTANT c_bre_ndx_w : NATURAL := c_high_bre_ndx-c_low_bre_ndx+1;
-- type for statemachine -- 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 -- record for readability
TYPE t_reg IS RECORD TYPE t_reg IS RECORD
...@@ -129,6 +131,9 @@ ARCHITECTURE rtl OF ddrctrl_controller IS ...@@ -129,6 +131,9 @@ ARCHITECTURE rtl OF ddrctrl_controller IS
state : t_state; state : t_state;
started : STD_LOGIC; started : STD_LOGIC;
-- stopping flush
timer : NATURAL;
-- stopping signals -- stopping signals
ready_for_set_stop : STD_LOGIC; ready_for_set_stop : STD_LOGIC;
stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0);
...@@ -152,7 +157,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS ...@@ -152,7 +157,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS
ddrctrl_ctrl_state : STD_LOGIC_VECTOR(32-1 DOWNTO 0); ddrctrl_ctrl_state : STD_LOGIC_VECTOR(32-1 DOWNTO 0);
END RECORD; 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 -- signals for readability
...@@ -173,32 +178,51 @@ BEGIN ...@@ -173,32 +178,51 @@ BEGIN
v := q_reg; v := q_reg;
v.wr_sosi := inp_sosi; 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_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_adr_ndx DOWNTO c_low_adr_ndx) := TO_UVEC(inp_adr, 32)(c_adr_ndx_w-1 DOWNTO 0);
CASE q_reg.state IS CASE q_reg.state IS
WHEN RESET => WHEN RESET =>
v := c_t_reg_init; v := c_t_reg_init;
v.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(0, c_state_ndx_w);
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.burstbegin := '1';
v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0');
v.dvr_mosi.wr := '1'; v.dvr_mosi.wr := '1';
ELSIF flush_state = "11" AND q_reg.timer = 0 THEN
v.wr_sosi.valid := '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); v.timer := 127;
END IF;
IF rst = '0' THEN IF q_reg.timer > 0 AND rst = '0' THEN
v.state := STOP_READING; v.timer := q_reg.timer-1;
END IF;
IF flush_state = "01" THEN
v.state := WAIT_FOR_SOP;
v.stopped := '0';
END IF; END IF;
WHEN STOP_READING => 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. -- 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 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.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.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.dvr_mosi.burstsize := TO_UVEC(q_reg.stop_burstsize, dvr_mosi.burstsize'length);
v.stopped := '0'; v.stopped := '0';
v.wr_sosi.valid := '0'; v.wr_sosi.valid := '1';
v.state := WAIT_FOR_SOP; v.state := WAIT_FOR_SOP;
v.wr_burst_en := '1'; v.wr_burst_en := '1';
v.rst_ddrctrl_input_ac := '1'; v.rst_ddrctrl_input_ac := '1';
...@@ -214,14 +238,14 @@ BEGIN ...@@ -214,14 +238,14 @@ BEGIN
WHEN WAIT_FOR_SOP => 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.ddrctrl_ctrl_state(c_high_state_ndx DOWNTO c_low_state_ndx) := TO_UVEC(3, c_state_ndx_w);
v.dvr_mosi.burstbegin := '1'; v.dvr_mosi.burstbegin := '0';
v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0'); v.dvr_mosi.burstsize(dvr_mosi.burstsize'length-1 DOWNTO 0) := (OTHERS => '0');
v.dvr_mosi.wr := '1'; v.dvr_mosi.wr := '1';
v.dvr_mosi.rd := '0'; v.dvr_mosi.rd := '0';
v.rst_ddrctrl_input_ac := '0'; v.rst_ddrctrl_input_ac := '0';
IF q_reg.started = '0' AND inp_sosi.eop = '1' THEN 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 ELSIF inp_sosi.sop = '1' THEN
v.state := WRITING; v.state := WRITING;
ELSE ELSE
...@@ -230,7 +254,7 @@ BEGIN ...@@ -230,7 +254,7 @@ BEGIN
WHEN WRITING => 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. -- 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)); 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 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 ...@@ -268,7 +292,7 @@ BEGIN
WHEN SET_STOP => 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. -- this state sets a stop address dependend on the g_stop_percentage.
IF inp_adr-c_pof_ma >= 0 THEN 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); v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr-c_pof_ma, c_adr_w);
...@@ -318,7 +342,7 @@ BEGIN ...@@ -318,7 +342,7 @@ BEGIN
WHEN STOP_WRITING => 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. -- this state stops the writing by generating one last whole write burst which almost empties wr_fifo.
v.wr_sosi.valid := '0'; v.wr_sosi.valid := '0';
v.dvr_mosi.burstbegin := '0'; v.dvr_mosi.burstbegin := '0';
...@@ -355,7 +379,7 @@ BEGIN ...@@ -355,7 +379,7 @@ BEGIN
WHEN LAST_WRITE_BURST => 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. -- this state stops the writing by generatign one last write burst which empties wr_fifo.
v.wr_sosi.valid := '0'; v.wr_sosi.valid := '0';
IF dvr_miso.done = '1' THEN IF dvr_miso.done = '1' THEN
...@@ -377,7 +401,7 @@ BEGIN ...@@ -377,7 +401,7 @@ BEGIN
WHEN START_READING => 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. -- 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.dvr_mosi.burstbegin := '0';
v.outp_bsn := INCR_UVEC(inp_sosi.bsn,-1*g_bim); v.outp_bsn := INCR_UVEC(inp_sosi.bsn,-1*g_bim);
...@@ -407,7 +431,7 @@ BEGIN ...@@ -407,7 +431,7 @@ BEGIN
WHEN READING => 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'; 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. -- 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 IF TO_UINT(rd_fifo_usedw) <= g_burstsize AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN
......
...@@ -39,6 +39,7 @@ ENTITY common_fifo_dc IS ...@@ -39,6 +39,7 @@ ENTITY common_fifo_dc IS
wr_clk : IN STD_LOGIC; wr_clk : IN STD_LOGIC;
wr_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0); wr_dat : IN STD_LOGIC_VECTOR(g_dat_w-1 DOWNTO 0);
wr_req : IN STD_LOGIC; wr_req : IN STD_LOGIC;
wr_init_out : OUT STD_LOGIC;
wr_ful : OUT STD_LOGIC; wr_ful : OUT STD_LOGIC;
wrusedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_nof_words)-1 DOWNTO 0); wrusedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_nof_words)-1 DOWNTO 0);
rd_clk : IN STD_LOGIC; rd_clk : IN STD_LOGIC;
...@@ -98,6 +99,8 @@ BEGIN ...@@ -98,6 +99,8 @@ BEGIN
out_rst => wr_init -- assume init has finished g_delay_len cycles after release of wr_rst 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 -- 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) 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) rd_en <= rd_req; -- check on NOT emp is not necessary when underflow_checking="ON" (Altera)
......
...@@ -111,6 +111,7 @@ ARCHITECTURE str OF dp_fifo_core IS ...@@ -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_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0);
SIGNAL fifo_wr_req : STD_LOGIC; SIGNAL fifo_wr_req : STD_LOGIC;
SIGNAL fifo_wr_ful : 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_wr_usedw : STD_LOGIC_VECTOR(wr_usedw'RANGE);
SIGNAL fifo_rd_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); SIGNAL fifo_rd_dat : STD_LOGIC_VECTOR(c_fifo_dat_w-1 DOWNTO 0) := (OTHERS=>'0');
...@@ -166,7 +167,7 @@ BEGIN ...@@ -166,7 +167,7 @@ BEGIN
nxt_snk_out.xon <= src_in.xon; nxt_snk_out.xon <= src_in.xon;
-- up stream use fifo almost full to control snk_out.ready -- 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 gen_common_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
u_common_fifo_sc : ENTITY common_lib.common_fifo_sc u_common_fifo_sc : ENTITY common_lib.common_fifo_sc
...@@ -205,6 +206,7 @@ BEGIN ...@@ -205,6 +206,7 @@ BEGIN
wr_clk => wr_clk, wr_clk => wr_clk,
wr_dat => fifo_wr_dat, wr_dat => fifo_wr_dat,
wr_req => fifo_wr_req, wr_req => fifo_wr_req,
wr_init_out => wr_init,
wr_ful => fifo_wr_ful, wr_ful => fifo_wr_ful,
wrusedw => fifo_wr_usedw, wrusedw => fifo_wr_usedw,
rd_clk => rd_clk, rd_clk => rd_clk,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment