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

Working

parent 4104dfcc
No related branches found
No related tags found
2 merge requests!245Resolve L2SDP-708,!242Resolve L2SDP-708
Pipeline #29121 failed
......@@ -52,7 +52,8 @@ ENTITY ddrctrl IS
g_nof_streams : NATURAL := 12; -- number of input streams
g_data_w : NATURAL := 14; -- data with of input data vectors
g_stop_percentage : NATURAL := 50;
g_block_size : NATURAL := 1024
g_block_size : NATURAL := 1024;
g_burstsize : NATURAL := 64
);
PORT (
clk : IN STD_LOGIC := '0';
......@@ -91,42 +92,42 @@ ARCHITECTURE str OF ddrctrl IS
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_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address
CONSTANT c_bim : NATURAL := (c_max_adr*c_io_ddr_data_w)/(g_block_size*g_nof_streams*g_data_w); -- the amount of whole blocks that fit in memory.
CONSTANT c_nof_adr : NATURAL := (c_bim*g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w; -- rounding error removes the amount of extra addresses.
CONSTANT c_adr_per_b : NATURAL := ((g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w)+1; -- rounding error removes the amount of extra addresses.
SIGNAL s_adr_per_b : NATURAL := c_adr_per_b;
-- the amount of addresses used
CONSTANT c_nof_adr : NATURAL := c_bim*c_adr_per_b;
SIGNAL s_nof_adr : NATURAL := c_nof_adr;
-- the amount of overflow after one block is written
CONSTANT c_of_pb : NATURAL := (g_block_size*g_nof_streams*g_data_w)-(((g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w)*c_io_ddr_data_w); -- amount of overflow after one block is written to memory
FUNCTION c_of_after_nof_adr_init RETURN NATURAL IS
VARIABLE temp : NATURAL := 0;
BEGIN
FOR I IN 0 TO c_bim-1 LOOP
IF temp+c_of_pb < c_io_ddr_data_w THEN
temp := temp+c_of_pb;
ELSE
temp := temp+c_of_pb-c_io_ddr_data_w;
END IF;
END LOOP;
RETURN temp;
END FUNCTION c_of_after_nof_adr_init;
CONSTANT c_of_after_nof_adr : NATURAL := c_of_after_nof_adr_init;
CONSTANT c_aof_full_burst : NATURAL := c_nof_adr/g_burstsize;
CONSTANT c_last_burstsize : NATURAL := c_nof_adr-(c_aof_full_burst*g_burstsize);
SIGNAL s_last_burstsize : NATURAL := c_last_burstsize;
-- signals for connecting the components
SIGNAL ctrl_clk : STD_LOGIC;
SIGNAL ctrl_rst : STD_LOGIC;
SIGNAL out_of : NATURAL := 0;
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL out_adr : NATURAL := 0;
SIGNAL dvr_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst;
SIGNAL dvr_miso : t_mem_ctlr_miso := c_mem_ctlr_miso_rst;
SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst;
SIGNAL rd_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL stop : STD_LOGIC;
SIGNAL rd_fifo_usedw: STD_LOGIC_VECTOR(c_rd_fifo_uw_w-1 DOWNTO 0);
SIGNAL rd_ready : STD_LOGIC;
SIGNAL inp_ds : NATURAL;
SIGNAL inp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
SIGNAL inp_bsn_adr : NATURAL;
SIGNAL outp_ds : NATURAL;
SIGNAL outp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
SIGNAL ctrl_clk : STD_LOGIC;
SIGNAL ctrl_rst : STD_LOGIC;
SIGNAL rst_ddrctrl_input : STD_LOGIC;
SIGNAL out_of : NATURAL := 0;
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL out_adr : NATURAL := 0;
SIGNAL dvr_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst;
SIGNAL dvr_miso : t_mem_ctlr_miso := c_mem_ctlr_miso_rst;
SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst;
SIGNAL rd_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL stop : STD_LOGIC;
SIGNAL rd_fifo_usedw : STD_LOGIC_VECTOR(c_rd_fifo_uw_w-1 DOWNTO 0);
SIGNAL rd_ready : STD_LOGIC;
SIGNAL inp_ds : NATURAL;
SIGNAL inp_bsn_adr : NATURAL;
SIGNAL outp_ds : NATURAL;
SIGNAL outp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
BEGIN
......@@ -137,20 +138,21 @@ BEGIN
u_ddrctrl_input : ENTITY work.ddrctrl_input
GENERIC MAP(
g_tech_ddr => g_tech_ddr,
g_sim_model => g_sim_model,
g_nof_streams => g_nof_streams,
g_data_w => g_data_w
g_data_w => g_data_w,
g_max_adr => c_nof_adr,
g_bim => c_bim,
g_of_pb => c_of_pb,
g_block_size => g_block_size
)
PORT MAP(
clk => clk,
rst => rst,
rst => rst_ddrctrl_input,
in_sosi_arr => in_sosi_arr,
in_stop => stop,
out_of => out_of,
out_sosi => out_sosi,
out_adr => out_adr,
out_bsn_ds => inp_ds,
out_bsn => inp_bsn,
out_bsn_adr => inp_bsn_adr
);
......@@ -161,7 +163,7 @@ BEGIN
g_technology => g_technology,
g_tech_ddr => g_tech_ddr,
g_cross_domain_dvr_ctlr => FALSE,
g_wr_data_w => c_io_ddr_data_w,
g_wr_data_w => c_io_ddr_data_w,
g_wr_fifo_depth => c_wr_fifo_depth,
g_rd_fifo_depth => c_rd_fifo_depth,
g_rd_data_w => c_io_ddr_data_w,
......@@ -261,7 +263,10 @@ BEGIN
g_rd_fifo_depth => c_rd_fifo_depth,
g_rd_data_w => c_io_ddr_data_w,
g_block_size => g_block_size,
g_rd_fifo_uw_w => c_rd_fifo_uw_w
g_rd_fifo_uw_w => c_rd_fifo_uw_w,
g_max_adr => c_nof_adr,
g_burstsize => g_burstsize,
g_last_burstsize => c_last_burstsize
)
PORT MAP(
clk => clk,
......@@ -272,8 +277,8 @@ BEGIN
inp_sosi => out_sosi,
inp_adr => out_adr,
inp_ds => inp_ds,
inp_bsn => inp_bsn,
inp_bsn_adr => inp_bsn_adr,
rst_ddrctrl_input => rst_ddrctrl_input,
-- io_ddr
dvr_mosi => dvr_mosi,
......
......@@ -46,19 +46,22 @@ ENTITY ddrctrl_controller IS
g_rd_fifo_depth : NATURAL;
g_rd_data_w : NATURAL;
g_block_size : NATURAL;
g_rd_fifo_uw_w : NATURAL
g_rd_fifo_uw_w : NATURAL;
g_max_adr : NATURAL;
g_burstsize : NATURAL;
g_last_burstsize : NATURAL
);
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_ds : IN NATURAL;
inp_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
inp_bsn_adr : IN NATURAL;
inp_of : IN NATURAL;
inp_sosi : IN t_dp_sosi;
inp_adr : IN NATURAL;
inp_ds : IN NATURAL;
inp_bsn_adr : IN NATURAL;
rst_ddrctrl_input : OUT STD_LOGIC;
-- io_ddr
dvr_mosi : OUT t_mem_ctlr_mosi;
......@@ -78,17 +81,15 @@ END ddrctrl_controller;
ARCHITECTURE rtl OF ddrctrl_controller IS
CONSTANT c_burstsize : NATURAL := 64; -- max burstsize for max troughput
CONSTANT c_bitshift_adr : NATURAL := ceil_log2(c_burstsize); -- bitshift to make sure there is only a burst start at a interval of c_burstsize.
CONSTANT c_bitshift_adr : 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_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address
CONSTANT c_pof_ma : NATURAL := (c_max_adr*(100-g_stop_percentage))/100;
CONSTANT c_pof_ma : NATURAL := (g_max_adr*(100-g_stop_percentage))/100;
CONSTANT c_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-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_max_read_cnt : NATURAL := (c_max_adr+1)/c_burstsize; -- 256
CONSTANT c_max_read_cnt : NATURAL := (g_max_adr+1)/g_burstsize; -- 256
-- type for statemachine
TYPE t_state IS (RESET, WRITING, SET_STOP, STOP_WRITING, START_READING, READING, STOP_READING, IDLE);
......@@ -97,10 +98,16 @@ ARCHITECTURE rtl OF ddrctrl_controller IS
TYPE t_reg IS RECORD
-- state of program
state : t_state;
started : STD_LOGIC;
-- stopping signals
stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0);
stopped : STD_LOGIC;
rst_ddrctrl_input : STD_LOGIC;
cooling_down : NATURAL;
-- writing signals
need_burst : STD_LOGIC;
-- reading signals
outp_ds : NATURAL;
......@@ -113,7 +120,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS
wr_sosi : t_dp_sosi;
END RECORD;
CONSTANT c_t_reg_init : t_reg := (RESET, TO_UVEC(c_max_adr, c_adr_w), '0', 0, (OTHERS => '0'), 0, '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init);
CONSTANT c_t_reg_init : t_reg := (RESET, '0', TO_UVEC(g_max_adr, c_adr_w), '1', '1', 8, '0', 0, (OTHERS => '0'), 0, '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init);
-- signals for readability
......@@ -125,7 +132,7 @@ 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_ds, inp_bsn, inp_bsn_adr, dvr_miso, rd_fifo_usedw, stop_in)
p_state : PROCESS(q_reg, rst, inp_of, inp_sosi, inp_adr, inp_ds, inp_bsn_adr, dvr_miso, rd_fifo_usedw, stop_in)
VARIABLE v : t_reg := c_t_reg_init;
......@@ -137,22 +144,32 @@ BEGIN
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';
WHEN WRITING =>
-- if adr mod c_burstsize = 0
-- if adr mod g_burstsize = 0
-- this makes sure that only ones every 64 writes a writeburst is started.
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros AND q_reg.dvr_mosi.burstbegin = '0'THEN
v.need_burst := '1';
END IF;
IF dvr_miso.done = '1' AND q_reg.need_burst = '1' THEN
v.dvr_mosi.burstbegin := '1';
IF inp_adr = 0 THEN
v.dvr_mosi.address := TO_UVEC(c_max_adr-c_burstsize, dvr_mosi.address'length);
v.need_burst := '0';
IF inp_adr < g_burstsize-1 THEN
v.dvr_mosi.address := TO_UVEC(g_max_adr-g_last_burstsize, 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-c_burstsize, dvr_mosi.address'length);
v.dvr_mosi.address := TO_UVEC(inp_adr-g_burstsize, dvr_mosi.address'length);
v.dvr_mosi.address(c_bitshift_adr-1 DOWNTO 0) := c_zeros(c_bitshift_adr-1 DOWNTO 0);
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.burstsize := TO_UVEC(c_burstsize, dvr_mosi.burstsize'length);
v.dvr_mosi.wr := '1';
v.dvr_mosi.rd := '0';
v.wr_sosi := inp_sosi;
......@@ -160,27 +177,28 @@ BEGIN
WHEN SET_STOP =>
--setting a stop address dependend on the g_stop_percentage
IF inp_adr+c_pof_ma >= c_max_adr THEN
IF inp_adr+c_pof_ma >= g_max_adr THEN
v.stop_adr(c_adr_w-1 DOWNTO c_bitshift_adr) := TO_UVEC(inp_adr-c_pof_ma, c_adr_w)(c_adr_w-1 DOWNTO c_bitshift_adr);
ELSE
v.stop_adr(c_adr_w-1 DOWNTO c_bitshift_adr) := TO_UVEC(inp_adr+c_pof_ma, c_adr_w)(c_adr_w-1 DOWNTO c_bitshift_adr);
END IF;
v.stop_adr(c_bitshift_adr-1 DOWNTO 0) := c_zeros;
v.cooling_down := 8;
-- still a write cyle
-- if adr mod c_burstsize = 0
-- if adr mod g_burstsize = 0
-- this makes sure that only ones every 64 writes a writeburst is started.
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN
v.dvr_mosi.burstbegin := '1';
IF inp_adr = 0 THEN
v.dvr_mosi.address := TO_UVEC(c_max_adr-c_burstsize, dvr_mosi.address'length);
v.dvr_mosi.address := TO_UVEC(g_max_adr-g_burstsize, dvr_mosi.address'length);
ELSE
v.dvr_mosi.address := TO_UVEC(inp_adr-c_burstsize, dvr_mosi.address'length);
v.dvr_mosi.address := TO_UVEC(inp_adr-g_burstsize, dvr_mosi.address'length);
END IF;
ELSE
v.dvr_mosi.burstbegin := '0';
END IF;
v.dvr_mosi.burstsize := TO_UVEC(c_burstsize, dvr_mosi.burstsize'length);
v.dvr_mosi.burstsize := TO_UVEC(g_burstsize, dvr_mosi.burstsize'length);
v.dvr_mosi.wr := '1';
v.dvr_mosi.rd := '0';
v.wr_sosi := inp_sosi;
......@@ -189,15 +207,41 @@ BEGIN
WHEN STOP_WRITING =>
v.dvr_mosi.burstbegin := '0';
-- wait until the write burst is finished
IF dvr_miso.done = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN
IF NOT (q_reg.cooling_down = 0) THEN
v.cooling_down := q_reg.cooling_down-1;
v.state := STOP_WRITING;
ELSIF dvr_miso.done = '1' AND q_reg.dvr_mosi.burstbegin = '0' THEN
v.stopped := '1';
v.wr_sosi.valid := '0';
v.dvr_mosi.flush := '1';
v.state := START_READING;
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.
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros AND q_reg.dvr_mosi.burstbegin = '0'THEN
v.need_burst := '1';
END IF;
IF dvr_miso.done = '1' AND q_reg.need_burst = '1' THEN
v.dvr_mosi.burstbegin := '1';
v.need_burst := '0';
IF inp_adr < g_burstsize-1 THEN
v.dvr_mosi.address := TO_UVEC(g_max_adr-g_last_burstsize, 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, dvr_mosi.address'length);
v.dvr_mosi.address(c_bitshift_adr-1 DOWNTO 0) := c_zeros(c_bitshift_adr-1 DOWNTO 0);
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';
v.wr_sosi := inp_sosi;
WHEN START_READING =>
v.rd_burst_en := '1';
......@@ -205,24 +249,24 @@ BEGIN
v.dvr_mosi.rd := '1';
v.outp_ds := inp_ds;
FOR I IN 0 TO inp_bsn_adr+(c_max_adr-TO_UINT(q_reg.stop_adr)) LOOP -- takes a while WRONG, wil be fixed after L2SDP-705, 706, 707 and 708
FOR I IN 0 TO inp_bsn_adr+(g_max_adr-TO_UINT(q_reg.stop_adr)) LOOP -- takes a while WRONG, wil be fixed after L2SDP-705, 706, 707 and 708
IF v.outp_ds-c_rest <= 0 THEN
v.outp_ds := v.outp_ds+c_rd_data_w-c_rest;
ELSE
v.outp_ds := v.outp_ds-c_rest;
END IF;
END LOOP;
v.outp_bsn := TO_UVEC(TO_UINT(inp_bsn), c_dp_stream_bsn_w); -- WRONG, wil be fixed after L2SDP-705, 706, 707 and 708
v.outp_bsn := TO_UVEC(TO_UINT(inp_sosi.bsn), c_dp_stream_bsn_w); -- WRONG, wil be fixed after L2SDP-705, 706, 707 and 708
v.state := READING;
WHEN READING =>
-- 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) <= 10 AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' AND dvr_miso.done = '1' THEN
IF TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt >= c_max_adr THEN
v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr-1, c_adr_w);
IF TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+g_burstsize*q_reg.read_cnt >= g_max_adr THEN
v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+g_burstsize*q_reg.read_cnt)-g_max_adr-1, c_adr_w);
ELSE
v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt, c_adr_w);
v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+g_burstsize*q_reg.read_cnt, c_adr_w);
END IF;
v.dvr_mosi.burstbegin := '1';
v.read_cnt := v.read_cnt+1;
......@@ -237,17 +281,29 @@ BEGIN
END IF;
IF q_reg.read_cnt >= c_max_read_cnt THEN
v.state := IDLE;
v.state := STOP_READING;
ELSE
v.state := READING;
END IF;
WHEN STOP_READING =>
IF dvr_miso.done = '1' THEN
v.rst_ddrctrl_input := '0';
v.stopped := '0';
v.state := IDLE;
ELSE
v.state := STOP_READING;
END IF;
WHEN IDLE =>
v.wr_sosi.valid := '0';
-- the statemachine goes to Idle when its finished or when its waiting on other components.
WHEN OTHERS =>
v := c_t_reg_init;
......@@ -260,10 +316,13 @@ BEGIN
v.state := SET_STOP;
ELSIF v.stop_adr = TO_UVEC(inp_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN
v.state := STOP_WRITING;
ELSIF v.stopped = '1' THEN
v.state := IDLE;
ELSE
ELSIF v.stopped = '0' AND inp_sosi.valid = '1' AND q_reg.started = '1' THEN
v.state := WRITING;
v.wr_sosi := inp_sosi;
ELSIF q_reg.stopped = '1' THEN
v.state := STOP_READING;
ELSE
v.state := IDLE;
END IF;
END IF;
......@@ -272,15 +331,21 @@ BEGIN
v.state := RESET;
END IF;
IF inp_sosi.eop = '1' THEN
v.started := '1';
v.wr_sosi.valid := '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;
outp_ds <= q_reg.outp_ds;
dvr_mosi <= q_reg.dvr_mosi;
wr_sosi <= q_reg.wr_sosi;
stop_out <= q_reg.stopped;
outp_bsn <= q_reg.outp_bsn;
outp_ds <= q_reg.outp_ds;
rst_ddrctrl_input <= q_reg.rst_ddrctrl_input OR rst;
END rtl;
......@@ -44,21 +44,22 @@ USE dp_lib.dp_stream_pkg.ALL;
ENTITY ddrctrl_input IS
GENERIC (
g_tech_ddr : t_c_tech_ddr; -- type of memory
g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation
g_nof_streams : NATURAL := 12; -- number of input streams
g_data_w : NATURAL := 14 -- data with of input data vectors
g_tech_ddr : t_c_tech_ddr; -- type of memory
g_nof_streams : NATURAL := 12; -- number of input streams
g_data_w : NATURAL := 14; -- data with of input data vectors
g_max_adr : NATURAL;
g_bim : NATURAL;
g_of_pb : NATURAL;
g_block_size : NATURAL
);
PORT (
clk : IN STD_LOGIC := '0';
rst : IN STD_LOGIC;
in_sosi_arr : IN t_dp_sosi_arr; -- input data
in_stop : IN STD_LOGIC;
out_of : OUT NATURAL; -- amount of internal overflow this output
out_sosi : OUT t_dp_sosi; -- output data
out_adr : OUT NATURAL;
out_bsn_ds : OUT NATURAL;
out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
out_bsn_adr : OUT NATURAL
);
END ddrctrl_input;
......@@ -71,12 +72,9 @@ ARCHITECTURE str OF ddrctrl_input IS
-- signals for connecting the components
SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);
SIGNAL sosi_p_rp : t_dp_sosi := c_dp_sosi_init;
SIGNAL sosi_rp_ac : t_dp_sosi := c_dp_sosi_init;
SIGNAL a_of : NATURAL := 0;
SIGNAL adr : NATURAL := 0;
SIGNAL bsn_wr : STD_LOGIC := '0';
SIGNAL bsn_ds : NATURAL := 0;
SIGNAL valid : STD_LOGIC := '0';
......@@ -98,41 +96,36 @@ BEGIN
-- resizes the input data vector so that the output data vector can be stored into the ddr memory
u_ddrctrl_input_repack : ENTITY work.ddrctrl_input_repack
GENERIC MAP(
g_tech_ddr => g_tech_ddr, -- type of memory
g_in_data_w => c_out_data_w -- the input data with
g_tech_ddr => g_tech_ddr, -- type of memory
g_in_data_w => c_out_data_w, -- the input data with
g_bim => g_bim,
g_of_pb => g_of_pb,
g_block_size => g_block_size
)
PORT MAP(
clk => clk,
rst => rst,
in_sosi => sosi_p_rp, -- input data
in_stop => in_stop,
in_adr => adr,
in_valid => valid,
out_of => a_of, -- amount of internal overflow
out_sosi => sosi_rp_ac, -- output data
out_bsn_ds => bsn_ds, -- amount of bits between adr [0] and sosi_arr[0][0] where bsn is assigned to
out_bsn_wr => bsn_wr
out_bsn_ds => bsn_ds -- amount of bits between adr [0] and sosi_arr[0][0] where bsn is assigned to
);
-- creates address by counting input valids
u_ddrctrl_input_address_counter : ENTITY work.ddrctrl_input_address_counter
GENERIC MAP(
g_tech_ddr => g_tech_ddr, -- type of memory
g_sim_model => g_sim_model -- determens if this is a simulation
g_max_adr => g_max_adr
)
PORT MAP(
clk => clk,
rst => rst,
in_sosi => sosi, -- input data
in_of => a_of,
in_bsn_wr => bsn_wr,
in_sosi => sosi_rp_ac, -- input data
in_bsn_ds => bsn_ds,
out_sosi => out_sosi, -- output data
out_of => out_of,
out_adr => adr,
out_bsn_adr => out_bsn_adr,
out_bsn_ds => out_bsn_ds,
out_bsn => out_bsn
out_bsn_ds => out_bsn_ds
);
END str;
......@@ -42,22 +42,17 @@ USE dp_lib.dp_stream_pkg.ALL;
ENTITY ddrctrl_input_address_counter IS
GENERIC (
g_tech_ddr : t_c_tech_ddr; -- type of memory
g_sim_model : BOOLEAN := TRUE -- determens if this is a simulation
g_max_adr : NATURAL
);
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
in_sosi : IN t_dp_sosi; -- input data
in_of : IN NATURAL;
in_bsn_wr : IN STD_LOGIC;
in_bsn_ds : IN NATURAL;
in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data
out_of : OUT NATURAL;
out_adr : OUT NATURAL;
out_bsn_adr : OUT NATURAL;
out_bsn_ds : OUT NATURAL;
out_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0)
out_bsn_ds : OUT NATURAL
);
END ddrctrl_input_address_counter;
......@@ -66,8 +61,6 @@ ARCHITECTURE rtl OF ddrctrl_input_address_counter IS
-- constants for readability
CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- the with of the input data and output data, 576
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_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address
-- type for statemachine
TYPE t_state IS (RESET, COUNTING, MAX, IDLE);
......@@ -75,20 +68,16 @@ ARCHITECTURE rtl OF ddrctrl_input_address_counter IS
-- record for readability
TYPE t_reg IS RECORD
state : t_state;
bsn_passed : STD_LOGIC;
out_sosi : t_dp_sosi;
out_of : NATURAL;
out_bsn_adr : NATURAL;
out_bsn_ds : NATURAL;
out_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
s_in_sosi : t_dp_sosi;
s_in_of : NATURAL;
s_in_bsn_wr : STD_LOGIC;
s_in_bsn_ds : NATURAL;
s_in_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
s_adr : NATURAL;
END RECORD;
CONSTANT c_t_reg_init : t_reg := (RESET, c_dp_sosi_init, 0, 0, 0, (OTHERS => '0'), c_dp_sosi_init, 0, '0', 0, (OTHERS => '0'), 0);
CONSTANT c_t_reg_init : t_reg := (RESET, '0', c_dp_sosi_init, 0, 0, c_dp_sosi_init, 0, 0);
-- signals for readability
......@@ -99,8 +88,8 @@ BEGIN
q_reg <= d_reg WHEN rising_edge(clk);
-- Increments the address each time in_sosi.valid = '1', if address = c_max_adr the address is reset to 0.
p_adr : PROCESS(rst, in_sosi, in_of, q_reg)
-- Increments the address each time in_sosi.valid = '1', if address = g_max_adr the address is reset to 0.
p_adr : PROCESS(rst, in_sosi, q_reg)
VARIABLE v : t_reg;
......@@ -108,23 +97,17 @@ BEGIN
v := q_reg;
-- compensate for delay in ddrctrl_input_address_counter
v.out_sosi.data(c_data_w-1 DOWNTO 0) := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0);
v.out_sosi.valid := q_reg.s_in_sosi.valid;
v.out_of := q_reg.s_in_of;
v.out_sosi := q_reg.s_in_sosi;
v.out_bsn_ds := q_reg.s_in_bsn_ds;
v.out_bsn := q_reg.s_in_bsn;
v.s_in_sosi := in_sosi;
v.s_in_of := in_of;
v.s_in_bsn_wr := in_bsn_wr;
v.s_in_bsn_ds := in_bsn_ds;
v.s_in_bsn := in_bsn;
CASE q_reg.state IS
WHEN RESET =>
v.s_adr := c_max_adr-1; -- when there is a reset the fifo in io_ddr always needs the first out_sosi.valid to stop flushing the data so the first data word always gets lost. if s_adr is set to 0 after a restart the word from s_adr 1 will be put at address 0 in memory.
v.s_adr := 0; -- when there is a reset the fifo in io_ddr always needs the first out_sosi.valid to stop flushing the data so the first data word always gets lost. if s_adr is set to 0 after a restart the word from s_adr 1 will be put at address 0 in memory.
IF q_reg.s_in_bsn_wr = '1' THEN
IF q_reg.s_in_sosi.sop = '1' THEN
v.out_bsn_adr := v.s_adr;
END IF;
......@@ -132,7 +115,7 @@ BEGIN
WHEN COUNTING =>
v.s_adr := q_reg.s_adr+1;
IF q_reg.s_in_bsn_wr = '1' THEN
IF q_reg.s_in_sosi.sop = '1' THEN
v.out_bsn_adr := v.s_adr;
END IF;
......@@ -140,20 +123,23 @@ BEGIN
WHEN MAX =>
v.s_adr := 0;
IF q_reg.s_in_bsn_wr = '1' THEN
IF q_reg.s_in_sosi.sop = '1' THEN
v.out_bsn_adr := v.s_adr;
END IF;
WHEN IDLE =>
IF NOT(q_reg.s_in_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) = in_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0)) THEN
v.bsn_passed := '1';
END IF;
END CASE;
IF rst = '1' THEN
v.state := RESET;
ELSIF q_reg.s_adr = c_max_adr AND in_sosi.valid = '1' THEN
ELSIF q_reg.s_adr = g_max_adr-1 AND in_sosi.valid = '1' AND q_reg.bsn_passed = '1' THEN
v.state := MAX;
ELSIF in_sosi.valid = '1' THEN
ELSIF in_sosi.valid = '1' AND q_reg.bsn_passed = '1' THEN
v.state := COUNTING;
ELSE
v.state := IDLE;
......@@ -163,11 +149,10 @@ BEGIN
END PROCESS;
-- fill outputs
out_sosi <= q_reg.out_sosi;
out_of <= q_reg.out_of;
out_adr <= q_reg.s_adr;
out_bsn_adr <= q_reg.out_bsn_adr;
out_bsn_ds <= q_reg.out_bsn_ds;
out_bsn <= q_reg.out_bsn;
out_sosi <= q_reg.out_sosi;
out_adr <= q_reg.s_adr;
out_bsn_adr <= q_reg.out_bsn_adr;
out_bsn_ds <= q_reg.out_bsn_ds;
out_sosi.bsn <= q_reg.out_sosi.bsn;
END rtl;
......@@ -38,7 +38,7 @@ ENTITY ddrctrl_input_pack IS
);
PORT (
in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- input data
out_sosi : OUT t_dp_sosi := c_t_dp_sosi_init -- output data
out_sosi : OUT t_dp_sosi := c_dp_sosi_init -- output data
);
END ddrctrl_input_pack;
......@@ -55,65 +55,10 @@ BEGIN
-- check if the input data is valid bij doing a and operation on all of them
p_valid : PROCESS(in_sosi_arr) IS
VARIABLE valid : STD_LOGIC;
BEGIN
valid := '1';
FOR I IN 0 TO g_nof_streams-1 LOOP
valid := valid AND in_sosi_arr(I).valid;
END LOOP;
out_sosi.valid <= valid;
END PROCESS;
-- check for sop
p_sop : PROCESS(in_sosi_arr) IS
VARIABLE sop : STD_LOGIC;
BEGIN
sop := '1'
FOR I IN 0 TO g_nof_streams-1 LOOP
sop := sop AND in_sosi_arr(I).sop;
END LOOP;
out_sosi.sop <= sop;
END PROCESS;
-- check for eop
p_eop : PROCESS(in_sosi_arr) IS
VARIABLE eop : STD_LOGIC;
BEGIN
eop := '1'
FOR I IN 0 TO g_nof_streams-1 LOOP
eop := eop AND in_sosi_arr(I).eop;
END LOOP;
out_sosi.eop <= eop;
END PROCESS;
-- check for bsn
p_bsn : PROCESS(in_sosi_arr) IS
VARIABLE correct_bsn : STD_LOGIC;
BEGIN
correct_bsn := '1';
FOR I IN 1 TO g_nof_streams-1 LOOP
IF in_sosi_arr(I-1).bsn = in_sosi_arr(I).bsn THEN
correct_bsn := correct_bsn AND '1';
ELSE
correct_bsn := correct_bsn AND '0';
END IF;
END LOOP;
IF correct_bsn = '1' THEN
out_sosi.bsn <= in_sosi_arr(0).bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
ELSE
out_sosi.bsn <= (OTHERS => '0');
END IF;
out_sosi.valid <= func_dp_stream_arr_and(in_sosi_arr, "VALID");
out_sosi.sop <= func_dp_stream_arr_and(in_sosi_arr, "SOP");
out_sosi.eop <= func_dp_stream_arr_and(in_sosi_arr, "EOP");
out_sosi.sync <= func_dp_stream_arr_and(in_sosi_arr, "SYNC");
out_sosi.bsn <= in_sosi_arr(0).bsn;
END rtl;
......@@ -45,7 +45,7 @@ ENTITY tb_ddrctrl IS
g_tech_ddr3 : t_c_tech_ddr := c_tech_ddr3_4g_800m_master;
g_tech_ddr4 : t_c_tech_ddr := c_tech_ddr4_4g_1600m;
g_stop_percentage : NATURAL := 80; -- percentage there needs to be already written in the ddr memory when a stop gets triggered
g_block_size : NATURAL := 1024 -- amount of samples that goes into one bsn
g_block_size : NATURAL := 1023 -- amount of samples that goes into one bsn
);
END tb_ddrctrl;
......@@ -59,7 +59,7 @@ ARCHITECTURE tb OF tb_ddrctrl IS
CONSTANT c_tech_ddr : t_c_tech_ddr := func_tech_sel_ddr(c_sim_model, c_sim_ddr, c_mem_ddr);
-- constants for readability
CONSTANT c_ctrl_data_w : NATURAL := func_tech_ddr_ctlr_data_w( c_tech_ddr ); -- 576
CONSTANT c_ctrl_data_w : NATURAL := func_tech_ddr_ctlr_data_w(c_tech_ddr); -- 576
CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168
-- constants for testbench
......@@ -70,34 +70,41 @@ ARCHITECTURE tb OF tb_ddrctrl IS
CONSTANT c_sim_length : NATURAL := (g_sim_length*c_ctrl_data_w)/c_in_data_w; -- amount of input words that get put into the DUT
-- constant for checking output data
CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( c_tech_ddr ); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27
CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w(c_tech_ddr); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27
CONSTANT c_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address
CONSTANT c_output_stop_adr : NATURAL := (c_max_adr+1)-((((c_max_adr+1)/64)*g_stop_percentage/100)*64);
CONSTANT c_output_ds : NATURAL := 144;
CONSTANT c_bim : NATURAL := (c_max_adr*c_io_ddr_data_w)/(g_block_size*g_nof_streams*g_data_w); -- the amount of whole blocks that fit in memory.
CONSTANT c_nof_adr : NATURAL := (c_bim*g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w; -- rounding error removes the amount of extra addresses.
CONSTANT c_of_pb : NATURAL := (g_block_size*g_nof_streams*g_data_w)-(((g_block_size*g_nof_streams*g_data_w)/c_io_ddr_data_w)*c_io_ddr_data_w); -- amount of overflow after one block is written to memory
CONSTANT c_bim : NATURAL := (c_max_adr*c_ctrl_data_w)/(g_block_size*g_nof_streams*g_data_w); -- the amount of whole blocks that fit in memory.
CONSTANT c_adr_per_b : NATURAL := ((g_block_size*g_nof_streams*g_data_w)/c_ctrl_data_w)+1; -- rounding error removes the amount of extra addresses.
-- the amount of addresses used
CONSTANT c_nof_adr : NATURAL := (c_bim*g_block_size*g_nof_streams*g_data_w)/c_ctrl_data_w; -- rounding error removes the amount of extra addresses.
-- the amount of overflow after one block is written
CONSTANT c_of_pb : NATURAL := (g_block_size*g_nof_streams*g_data_w)-(((g_block_size*g_nof_streams*g_data_w)/c_ctrl_data_w)*c_ctrl_data_w); -- amount of overflow after one block is written to memory
FUNCTION c_of_after_nof_adr_init RETURN NATURAL IS
VARIABLE temp : NATURAL := 0;
BEGIN
FOR I IN 0 TO c_bim-1 LOOP
IF temp+c_of_pb < c_io_ddr_data_w THEN
IF temp+c_of_pb < c_ctrl_data_w THEN
temp := temp+c_of_pb;
ELSE
temp := temp+c_of_pb-c_io_ddr_data_w;
temp := temp+c_of_pb-c_ctrl_data_w;
END IF;
END LOOP;
RETURN temp;
END FUNCTION c_of_after_nof_adr_init;
-- the amount of overflow into the address: c_nof_adr
CONSTANT c_of_after_nof_adr : NATURAL := c_of_after_nof_adr_init;
-- function for making total data vector
FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS
VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*c_sim_length-1 DOWNTO 0);
VARIABLE temp : STD_LOGIC_VECTOR(g_data_w*g_nof_streams*c_bim*g_block_size-1 DOWNTO 0);
VARIABLE conv : STD_LOGIC_VECTOR(32-1 DOWNTO 0) := (OTHERS => '0'); -- removes a warning
BEGIN
FOR I IN 0 TO c_sim_length-1 LOOP
FOR I IN 0 TO c_bim*g_block_size-1 LOOP
conv := TO_UVEC(I, 32);
FOR J IN 0 TO g_nof_streams-1 LOOP
temp(g_data_w*((I*g_nof_streams)+J+1)-1 DOWNTO g_data_w*((I*g_nof_streams)+j)) := conv(g_data_w-1 DOWNTO 0);
......@@ -107,7 +114,7 @@ ARCHITECTURE tb OF tb_ddrctrl IS
END FUNCTION c_total_vector_init;
-- constant for running the test
CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*c_sim_length-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector
CONSTANT c_total_vector : STD_LOGIC_VECTOR(g_data_w*g_nof_streams*c_bim*g_block_size-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector
CONSTANT c_check : NATURAL := 32;
CONSTANT c_check_bottom : NATURAL := 5;
......@@ -130,6 +137,8 @@ ARCHITECTURE tb OF tb_ddrctrl IS
-- signals for running test
SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd
SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started
SIGNAL bsn_cnt : NATURAL := 0;
-- signals for checking the output data
SIGNAL output_data_cnt : NATURAL := 0;
......@@ -164,17 +173,36 @@ BEGIN
test_running <= '1';
WAIT FOR c_clk_period*1;
-- wr fifo has delay of 4 clockcylces after reset
-- filling the input data vectors with the corresponding numbers
run_multiple_times : FOR K in 0 TO 4 LOOP
make_data : FOR J IN 0 TO c_sim_length-1 LOOP
make_data : FOR J IN 0 TO c_bim*g_block_size-1 LOOP
in_data_cnt <= in_data_cnt+1;
fill_in_sosi_arr_0 : FOR I IN 0 TO g_nof_streams-1 LOOP
fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w);
in_sosi_arr(I).valid <= '1';
in_sosi_arr(I).bsn(c_dp_stream_bsn_w-1 DOWNTO 0) <= bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
IF bsn_cnt = g_block_size-1 THEN
bsn_cnt <= 0;
FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).sop <= '1';
in_sosi_arr(I).eop <= '0';
END LOOP;
bsn <= INCR_UVEC(bsn, 1);
ELSE
bsn_cnt <= bsn_cnt + 1;
FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).sop <= '0';
END LOOP;
END IF;
IF bsn_cnt = g_block_size-2 THEN
FOR I IN 0 TO g_nof_streams-1 LOOP
in_sosi_arr(I).eop <= '1';
END LOOP;
END IF;
END LOOP;
IF K = 1 AND J = 0 THEN
IF K = 2 AND J = c_bim*g_block_size-1 THEN
stop_in <= '1';
ELSE
stop_in <= '0';
......@@ -182,33 +210,18 @@ BEGIN
WAIT FOR c_clk_period*1;
END LOOP;
END LOOP;
in_sosi_arr(0).valid <= '0';
test_running <= '0';
-- stopping the testbench
WAIT FOR c_clk_period*4;
WAIT FOR c_clk_period*1024;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
p_bsn : PROCESS
VARIABLE bsn_cnt : NATURAL := 0;
BEGIN
bsn(c_check-1 DOWNTO c_check_bottom) <= c_ones(c_check-c_check_bottom-1 DOWNTO 0);
FOR I IN 0 TO (c_sim_length*4)-1 LOOP
WAIT UNTIL rising_edge(clk);
IF in_sosi_arr(0).valid = '1' THEN
IF bsn_cnt = g_block_size-1 THEN
bsn_cnt := 0;
bsn <= INCR_UVEC(bsn, 1);
ELSE
bsn_cnt := bsn_cnt + 1;
END IF;
END IF;
END LOOP;
END PROCESS;
p_checking_output_data : PROCESS -- first do tickets L2SDP-708 and L2SDP-707 before finsishing this is worth time
BEGIN
WAIT UNTIL rising_edge(clk);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment