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

initial commit

parent 022d9cdb
Branches
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 a_of : NATURAL := 0;
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