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

initial commit

parent 022d9cdb
No related branches found
No related tags found
1 merge request!228Resolve L2SDP-666
hdl_lib_name = lofar2_ddrctrl
hdl_library_clause_name = lofar2_ddrctrl_lib
hdl_lib_uses_synth = technology common tech_ddr dp
hdl_lib_uses_synth = technology common tech_ddr dp io_ddr
hdl_lib_uses_sim =
hdl_lib_technology =
......@@ -8,12 +8,14 @@ synth_files =
src/vhdl/ddrctrl_address_counter.vhd
src/vhdl/ddrctrl_pack.vhd
src/vhdl/ddrctrl_repack.vhd
src/vhdl/ddrctrl_input.vhd
src/vhdl/ddrctrl.vhd
test_bench_files =
tb/vhdl/tb_ddrctrl_address_counter.vhd
tb/vhdl/tb_ddrctrl_pack.vhd
tb/vhdl/tb_ddrctrl_repack.vhd
tb/vhdl/tb_ddrctrl_input.vhd
tb/vhdl/tb_ddrctrl.vhd
regression_test_vhdl =
......
......@@ -32,29 +32,46 @@
-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding
-- The maximum value of the address is determend by g_tech_ddr.
LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib, io_ddr_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE technology_lib.technology_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE io_ddr_lib.ALL;
ENTITY ddrctrl IS
GENERIC (
g_tech_ddr : t_c_tech_ddr; -- type of memory
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_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
g_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
);
PORT (
clk : IN STD_LOGIC := '0';
rst : IN STD_LOGIC;
in_sosi_arr : IN t_dp_sosi_arr; -- input data
out_of : OUT NATURAL; -- amount of internal overflow this output
out_mosi : OUT t_mem_ctlr_mosi -- output data
term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol;
term_ctrl_in : IN t_tech_ddr3_phy_terminationcontrol := c_tech_ddr3_phy_terminationcontrol_rst;
-- DDR3 PHY external interface
phy3_in : IN t_tech_ddr3_phy_in := c_tech_ddr3_phy_in_x;
phy3_io : INOUT t_tech_ddr3_phy_io;
phy3_ou : OUT t_tech_ddr3_phy_ou;
-- DDR4 PHY external interface
phy4_in : IN t_tech_ddr4_phy_in := c_tech_ddr4_phy_in_x;
phy4_io : INOUT t_tech_ddr4_phy_io;
phy4_ou : OUT t_tech_ddr4_phy_ou
);
END ddrctrl;
......@@ -62,16 +79,25 @@ END ddrctrl;
ARCHITECTURE str OF ddrctrl IS
-- constant for readability
CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data with for ddrctrl_repack
CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data width for ddrctrl_repack 168
CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr );
-- signals for connecting the components
SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0);
SIGNAL sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL adr : NATURAL := 0;
SIGNAL a_of : NATURAL := 0;
SIGNAL ctrl_clk : STD_LOGIC := '0';
SIGNAL ctrl_rst : STD_LOGIC := '0';
SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init;
SIGNAL wr_siso : t_dp_siso;
SIGNAL rd_siso : t_dp_siso;
SIGNAL dvr_mosi : t_mem_ctlr_mosi;
BEGIN
dvr_mosi.address <= TO_UVEC(adr, dvr_mosi.address'length);
-- makes one data vector out of all the data from the t_dp_sosi_arr
u_pack : ENTITY work.ddrctrl_pack
GENERIC MAP(
......@@ -112,8 +138,83 @@ BEGIN
rst => rst,
in_sosi => sosi, -- input data
in_of => a_of,
out_mosi => out_mosi, -- output data
out_of => out_of
out_sosi => wr_sosi, -- output data
out_of => out_of,
out_adr => adr
);
-- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick.
u_io_ddr : ENTITY io_ddr_lib.io_ddr
GENERIC MAP(
g_sim_model => g_sim_model,
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_fifo_depth => g_wr_fifo_depth,
g_rd_fifo_depth => g_rd_fifo_depth,
g_rd_data_w => c_io_ddr_data_w,
g_wr_flush_mode => "VAL",
g_wr_flush_use_channel => FALSE,
g_wr_flush_start_channel => 0,
g_wr_flush_nof_channels => 1
)
PORT MAP(
-- DDR reference clock
ctlr_ref_clk => clk,
ctlr_ref_rst => rst,
-- DDR controller clock domain
ctlr_clk_out => ctrl_clk,
ctlr_rst_out => ctrl_rst,
ctlr_clk_in => ctrl_clk,
ctlr_rst_in => ctrl_rst,
-- MM clock + reset
mm_rst => rst,
mm_clk => clk,
-- MM interface
reg_io_ddr_mosi => open,
reg_io_ddr_miso => open,
-- Driver clock domain
dvr_clk => clk,
dvr_rst => rst,
dvr_miso => open,
dvr_mosi => dvr_mosi,
-- Write FIFO clock domain
wr_clk => clk,
wr_rst => rst,
wr_fifo_usedw => open,
wr_sosi => wr_sosi,
wr_siso => wr_siso,
-- Read FIFO clock domain
rd_clk => clk,
rd_rst => rst,
rd_fifo_usedw => open,
rd_sosi => open,
rd_siso => rd_siso,
term_ctrl_out => term_ctrl_out,
term_ctrl_in => term_ctrl_in,
-- DDR3 PHY external interface
phy3_in => phy3_in,
phy3_io => phy3_io,
phy3_ou => phy3_ou,
-- DDR4 PHY external interface
phy4_in => phy4_in,
phy4_io => phy4_io,
phy4_ou => phy4_ou
);
END str;
......@@ -49,8 +49,9 @@ ENTITY ddrctrl_address_counter IS
rst : IN STD_LOGIC;
in_sosi : IN t_dp_sosi; -- input data
in_of : IN NATURAL;
out_mosi : OUT t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output data
out_of : OUT NATURAL
out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data
out_of : OUT NATURAL;
out_adr : OUT NATURAL
);
END ddrctrl_address_counter;
......@@ -60,7 +61,7 @@ ARCHITECTURE rtl OF ddrctrl_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 := sel_a_b(g_sim_model, 4, 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 : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(2**(c_adr_w)-1, c_adr_w)); -- the maximal address that is possible within the vector length of the address
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);
......@@ -68,13 +69,14 @@ ARCHITECTURE rtl OF ddrctrl_address_counter IS
-- record for readability
TYPE t_reg IS RECORD
state : t_state;
out_mosi : t_mem_ctlr_mosi;
out_sosi : t_dp_sosi;
out_of : NATURAL;
s_in_sosi : t_dp_sosi;
s_in_of : NATURAL;
s_adr : NATURAL;
END RECORD;
CONSTANT c_t_reg_init : t_reg := (RESET, c_mem_ctlr_mosi_rst, 0, c_dp_sosi_init, 0);
CONSTANT c_t_reg_init : t_reg := (RESET, c_dp_sosi_init, 0, c_dp_sosi_init, 0, 0);
-- signals for readability
......@@ -92,8 +94,8 @@ BEGIN
BEGIN
v := q_reg;
v.out_mosi.wrdata(c_data_w-1 DOWNTO 0) := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0);
v.out_mosi.wr := q_reg.s_in_sosi.valid;
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.s_in_sosi := in_sosi;
v.s_in_of := in_of;
......@@ -101,13 +103,13 @@ BEGIN
CASE q_reg.state IS
WHEN RESET =>
v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0');
v.s_adr := 0;
WHEN COUNTING =>
v.out_mosi.address(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(TO_UINT(q_reg.out_mosi.address)+1, c_adr_w));
v.s_adr := q_reg.s_adr+1;
WHEN MAX =>
v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0');
v.s_adr := 0;
WHEN IDLE =>
......@@ -115,7 +117,7 @@ BEGIN
IF rst = '1' THEN
v.state := RESET;
ELSIF q_reg.out_mosi.address(c_adr_w-1 DOWNTO 0) = c_max_adr(c_adr_w-1 DOWNTO 0) AND in_sosi.valid = '1' THEN
ELSIF q_reg.s_adr = c_max_adr AND in_sosi.valid = '1' THEN
v.state := MAX;
ELSIF in_sosi.valid = '1' THEN
v.state := COUNTING;
......@@ -127,7 +129,8 @@ BEGIN
END PROCESS;
-- fill outputs
out_mosi <= q_reg.out_mosi;
out_sosi <= q_reg.out_sosi;
out_of <= q_reg.out_of;
out_adr <= q_reg.s_adr;
END rtl;
......@@ -40,7 +40,9 @@ ENTITY tb_ddrctrl IS
g_nof_streams : POSITIVE := 12; -- number of input streams
g_data_w : NATURAL := 14; -- data with of input data vectors
g_sim_length : NATURAL := 52
g_technology : NATURAL := c_tech_select_default;
g_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
g_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
);
END tb_ddrctrl;
......@@ -195,15 +197,17 @@ BEGIN
GENERIC MAP (
g_tech_ddr => g_tech_ddr,
g_sim_model => g_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_wr_fifo_depth => g_wr_fifo_depth,
g_rd_fifo_depth => g_rd_fifo_depth
)
PORT MAP (
clk => clk,
rst => rst,
in_sosi_arr => in_sosi_arr,
out_of => out_of,
out_mosi => out_mosi
);
END tb;
......@@ -61,7 +61,8 @@ ARCHITECTURE tb OF tb_ddrctrl_address_counter IS
SIGNAL in_of : NATURAL := 0; -- signal which contains the amount of overflow
-- output signal from ddrctrl_address_counter.vhd
SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- signal which is the output from ddrctrl_address_counter.vhd
SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- signal which is the output from ddrctrl_address_counter.vhd
SIGNAL out_adr : NATURAL := 0;
SIGNAL out_of : NATURAL := 0; -- signal which is the output from ddrctrl_address_counter.vhd
-- testbench signals
......@@ -112,8 +113,8 @@ BEGIN
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
-- generating compare data for out_mosi
p_out_mosi : PROCESS
-- generating compare data for out_sosi
p_out_sosi : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
if rising_edge(clk) THEN
......@@ -128,10 +129,10 @@ BEGIN
q_rst <= rst;
END IF;
IF q_rst = '1' THEN
IF lag_due_reset + TO_UINT(out_mosi.address) >= c_adr_size THEN
lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_adr_size;
IF lag_due_reset + out_adr >= c_adr_size THEN
lag_due_reset <= lag_due_reset+out_adr-c_adr_size;
ELSE
lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address);
lag_due_reset <= lag_due_reset+out_adr;
END IF;
END IF;
END PROCESS;
......@@ -142,8 +143,8 @@ BEGIN
BEGIN
WAIT UNTIL rising_edge(clk);
IF rising_edge(clk) THEN
ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_mosi.wrdata(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_mosi.wrdata" SEVERITY ERROR;
ASSERT q_q_in_data_enable = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR;
ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_sosi.data(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_sosi.wrdata" SEVERITY ERROR;
ASSERT q_q_in_data_enable = out_sosi.valid REPORT "in_sosi.valid does not match out_sosi.wr" SEVERITY ERROR;
ASSERT q_q_in_of = out_of REPORT "in_of does not match out_of" SEVERITY ERROR;
END IF;
END PROCESS;
......@@ -162,13 +163,13 @@ BEGIN
BEGIN
FOR I IN 0 TO c_adr_size-1 LOOP
IF I >= q_lag_due_reset THEN
ASSERT I-q_lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR;
ASSERT I-q_lag_due_reset = out_adr REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
ELSE
ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR;
ASSERT (I-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR;
END IF;
WAIT UNTIL out_mosi.wr = '1';
WAIT UNTIL out_sosi.valid = '1';
IF q_q_rst = '1' THEN
WAIT UNTIL out_mosi.wr = '1';
WAIT UNTIL out_sosi.valid = '1';
END IF;
END LOOP;
END PROCESS;
......@@ -186,8 +187,9 @@ BEGIN
in_sosi => in_sosi,
in_of => in_of,
out_mosi => out_mosi,
out_of => out_of
out_sosi => out_sosi,
out_of => out_of,
out_adr => out_adr
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment