Skip to content
Snippets Groups Projects
Commit 36562913 authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

Merge branch 'L2SDP-667' into 'master'

Resolve L2SDP-667

Closes L2SDP-667

See merge request desp/hdl!232
parents 37087f0e 3bc43cc9
No related branches found
No related tags found
Loading
Pipeline #28137 passed
......@@ -9,6 +9,7 @@ synth_files =
src/vhdl/ddrctrl_input_pack.vhd
src/vhdl/ddrctrl_input_repack.vhd
src/vhdl/ddrctrl_input.vhd
src/vhdl/ddrctrl_controller.vhd
src/vhdl/ddrctrl.vhd
test_bench_files =
......
......@@ -50,8 +50,9 @@ ENTITY ddrctrl IS
g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation
g_technology : NATURAL := c_tech_select_default;
g_nof_streams : NATURAL := 12; -- number of input streams
g_data_w : NATURAL := 14 -- data with of input data vectors
);
g_data_w : NATURAL := 14; -- data with of input data vectors
g_stop_percentage : NATURAL := 50
);
PORT (
clk : IN STD_LOGIC := '0';
rst : IN STD_LOGIC;
......@@ -59,8 +60,7 @@ ENTITY ddrctrl IS
mm_rst : IN STD_LOGIC := '0';
in_sosi_arr : IN t_dp_sosi_arr; -- input data
wr_not_rd : IN STD_LOGIC := '0';
out_of : OUT NATURAL; -- amount of internal overflow this output
out_adr : OUT NATURAL;
stop_in : IN STD_LOGIC := '0';
term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol;
......@@ -85,40 +85,20 @@ ARCHITECTURE str OF ddrctrl IS
CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr );
CONSTANT c_wr_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 and independent of wr burst size, default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K
CONSTANT c_rd_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 AND > max number of rd burst sizes (so > c_rd_fifo_af_margin), default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K
CONSTANT c_burstsize : NATURAL := 64; -- max burstsize for max troughput
CONSTANT c_bitshift_adr : NATURAL := ceil_log2(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_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-1 DOWNTO 0) := (OTHERS => '0');
-- signals for connecting the components
SIGNAL adr : NATURAL := 0;
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 wr_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst;
SIGNAL dvr_mosi : t_mem_ctlr_mosi;
BEGIN
p_burst : PROCESS(adr)
BEGIN
IF TO_UVEC(adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN
dvr_mosi.burstbegin <= '1';
IF adr = 0 THEN
dvr_mosi.address <= TO_UVEC(c_max_adr-c_burstsize, dvr_mosi.address'length);
ELSE
dvr_mosi.address <= TO_UVEC(adr-c_burstsize, dvr_mosi.address'length);
END IF;
ELSE
dvr_mosi.burstbegin <= '0';
END IF;
END PROCESS;
dvr_mosi.burstsize <= TO_UVEC(c_burstsize, dvr_mosi.burstsize'length);
dvr_mosi.wr <= wr_not_rd;
dvr_mosi.rd <= NOT wr_not_rd;
-- input to io_ddr
u_ddrctrl_input : ENTITY work.ddrctrl_input
......@@ -133,8 +113,8 @@ BEGIN
rst => rst,
in_sosi_arr => in_sosi_arr,
out_of => out_of,
out_sosi => wr_sosi,
out_adr => adr
out_sosi => out_sosi,
out_adr => out_adr
);
-- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick.
......@@ -211,4 +191,25 @@ BEGIN
phy4_ou => phy4_ou
);
-- controller of ddrctrl
u_ddrctrl_controller : ENTITY work.ddrctrl_controller
GENERIC MAP(
g_tech_ddr => g_tech_ddr,
g_stop_percentage => g_stop_percentage
)
PORT MAP(
clk => clk,
rst => rst,
inp_of => out_of,
inp_sosi => out_sosi,
inp_adr => out_adr,
dvr_mosi => dvr_mosi,
wr_sosi => wr_sosi,
rd_siso => rd_siso,
stop_in => stop_in
);
END str;
-------------------------------------------------------------------------------
--
-- 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
);
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;
-- io_ddr
dvr_mosi : OUT t_mem_ctlr_mosi;
wr_sosi : OUT t_dp_sosi;
rd_siso : OUT t_dp_siso;
-- ddrctrl
stop_in : IN STD_LOGIC
);
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_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_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-1 DOWNTO 0) := (OTHERS => '0');
-- type for statemachine
TYPE t_state IS (RESET, WRITING, SET_STOP, STOP_WRITING, READING, STOP_READING, IDLE);
-- record for readability
TYPE t_reg IS RECORD
-- state of program
state : t_state;
-- signals
stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0);
stopped : STD_LOGIC;
-- output
dvr_mosi : t_mem_ctlr_mosi;
wr_sosi : t_dp_sosi;
rd_siso : t_dp_siso;
END RECORD;
CONSTANT c_t_reg_init : t_reg := (RESET, TO_UVEC(c_max_adr, c_adr_w), '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init, c_dp_siso_rst);
-- 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)
VARIABLE v : t_reg := c_t_reg_init;
BEGIN
v := q_reg;
CASE q_reg.state IS
WHEN RESET =>
v := c_t_reg_init;
WHEN WRITING =>
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN -- if adr mod c_burstsize = 0
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);
ELSE
v.dvr_mosi.address := TO_UVEC(inp_adr-c_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.wr := '1';
v.dvr_mosi.rd := '0';
v.wr_sosi := inp_sosi;
WHEN SET_STOP =>
--setting a stop address dependend on the g_stop_percentage
IF inp_adr+c_pof_ma >= c_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;
-- still a write cyle
IF TO_UVEC(inp_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN -- adr mod 64 = 0
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);
ELSE
v.dvr_mosi.address := TO_UVEC(inp_adr-c_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.wr := '1';
v.dvr_mosi.rd := '0';
v.wr_sosi := inp_sosi;
WHEN STOP_WRITING =>
v.stopped := '1';
v.wr_sosi.valid := '0';
v.dvr_mosi.flush := '1';
WHEN IDLE =>
WHEN OTHERS =>
v := c_t_reg_init;
END CASE;
IF rst = '1' THEN
v.state := RESET;
ELSIF stop_in = '1' THEN
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
v.state := WRITING;
END IF;
d_reg <= v;
END PROCESS;
-- fill outputs
dvr_mosi <= q_reg.dvr_mosi;
wr_sosi <= q_reg.wr_sosi;
rd_siso <= q_reg.rd_siso;
END rtl;
......@@ -71,6 +71,7 @@ ARCHITECTURE rtl OF ddrctrl_input_repack IS
CONSTANT c_t_reg_init : t_reg := (RESET, 0, (OTHERS => '0'), 0, 0, 0, c_dp_sosi_init);
-- signals for readability
SIGNAL d_reg : t_reg := c_t_reg_init;
SIGNAL q_reg : t_reg := c_t_reg_init;
......
......@@ -33,6 +33,7 @@ USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY tb_ddrctrl IS
GENERIC (
......@@ -42,7 +43,8 @@ ENTITY tb_ddrctrl IS
g_sim_length : NATURAL := 16500; -- close to the amount of word that gets put into the memory
g_technology : NATURAL := c_tech_select_default;
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_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
);
END tb_ddrctrl;
......@@ -88,6 +90,7 @@ ARCHITECTURE tb OF tb_ddrctrl IS
SIGNAL mm_rst : STD_LOGIC := '0';
SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input data signal for ddrctrl_pack.vhd
SIGNAL wr_not_rd : STD_LOGIC;
SIGNAL stop_in : STD_LOGIC := '0';
-- testbench signal
......@@ -128,16 +131,24 @@ BEGIN
-- filling the input data vectors with the corresponding numbers
make_data : FOR J IN 0 TO c_sim_length-1 LOOP
in_data_cnt <= in_data_cnt+1;
fill_in_sosi_arr_rest : 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);
run_multiple_times : FOR K in 0 TO 4 LOOP
make_data : FOR J IN 0 TO c_sim_length-1 LOOP
in_data_cnt <= in_data_cnt+1;
fill_in_sosi_arr_0 : 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);
END LOOP;
WAIT FOR c_clk_period*1;
END LOOP;
WAIT FOR c_clk_period*1;
IF k = 2 THEN
stop_in <= '1';
ELSE
stop_in <= '0';
END IF;
END LOOP;
test_running <= '0';
wr_not_rd <= '0';
-- stopping the testbench
WAIT FOR c_clk_period*4;
tb_end <= '1';
......@@ -154,7 +165,8 @@ BEGIN
g_sim_model => c_sim_model,
g_technology => g_technology,
g_nof_streams => g_nof_streams,
g_data_w => g_data_w
g_data_w => g_data_w,
g_stop_percentage => g_stop_percentage
)
PORT MAP (
clk => clk,
......@@ -163,8 +175,7 @@ BEGIN
mm_rst => mm_rst,
in_sosi_arr => in_sosi_arr,
wr_not_rd => wr_not_rd,
out_of => open,
out_adr => open,
stop_in => stop_in,
--PHY
phy3_io => phy3_io,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment