Skip to content
Snippets Groups Projects
Commit 61a1e8cf authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Merge branch 'master' into L2SDP-665

parents 11188289 36562913
Branches
No related tags found
1 merge request!234Use g_round_even = false in tb, because golden results use round half away...
Pipeline #28307 passed
Pipeline: sdptr

#28308

    ......@@ -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,7 +50,8 @@ 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';
    ......@@ -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
    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_rest : FOR I IN 0 TO g_nof_streams-1 LOOP
    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;
    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.
    Please register or to comment