Select Git revision
ddr3_transpose.vhd

Eric Kooistra authored
Do not assign default value for g_reset in common_fifo_sc. To avoid clutter in report when using e.g.: grep -rl 'g_reset ' libraries.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ddr3_transpose.vhd 14.29 KiB
--------------------------------------------------------------------------------
--
-- Copyright (C) 2011
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
library IEEE, common_lib, dp_lib, ss_lib, tech_ddr_lib;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.all;
use dp_lib.dp_stream_pkg.all;
use tech_ddr_lib.tech_ddr_pkg.all;
use work.ddr3_pkg.all;
entity ddr3_transpose is
generic(
g_sim : boolean := false;
g_nof_streams : natural := 4;
g_in_dat_w : natural := 8;
g_frame_size_in : natural := 256;
g_frame_size_out : natural := 256;
g_nof_blk_per_sync : natural := 16;
g_use_complex : boolean := true;
g_ena_pre_transp : boolean := true;
g_phy : natural := 1; -- 0: ALTMEMPHY 1: UNIPHY_MASTER 2: UNIPHY_SLAVE
g_mts : natural := 800; -- Megatransfers per second
g_ddr3_seq : t_ddr3_seq := c_ddr3_seq;
g_select_file : string := "UNUSED"
);
port (
mm_rst : in std_logic; -- reset synchronous with mm_clk
mm_clk : in std_logic; -- memory-mapped bus clock
dp_ref_clk : in std_logic;
dp_ref_rst : in std_logic;
dp_clk : in std_logic;
dp_rst : in std_logic;
dp_out_clk : out std_logic;
dp_out_rst : out std_logic;
-- MM register map for DDR controller status info
reg_io_ddr_mosi : in t_mem_mosi := c_mem_mosi_rst;
reg_io_ddr_miso : out t_mem_miso;
-- ST sinks
snk_out_arr : out t_dp_siso_arr(g_nof_streams - 1 downto 0);
snk_in_arr : in t_dp_sosi_arr(g_nof_streams - 1 downto 0);
-- ST source
src_in_arr : in t_dp_siso_arr(g_nof_streams - 1 downto 0);
src_out_arr : out t_dp_sosi_arr(g_nof_streams - 1 downto 0);
-- Memory Mapped
ram_ss_ss_transp_mosi : in t_mem_mosi; -- channel select control
ram_ss_ss_transp_miso : out t_mem_miso;
ser_term_ctrl_out : out std_logic_vector(13 downto 0);
par_term_ctrl_out : out std_logic_vector(13 downto 0);
ser_term_ctrl_in : in std_logic_vector(13 downto 0) := (others => '0');
par_term_ctrl_in : in std_logic_vector(13 downto 0) := (others => '0');
phy_in : in t_tech_ddr3_phy_in;
phy_io : inout t_tech_ddr3_phy_io;
phy_ou : out t_tech_ddr3_phy_ou
);
end ddr3_transpose;
architecture str of ddr3_transpose is
constant c_min_fifo_size : positive := 256;
constant c_blocksize : positive := g_ddr3_seq.wr_nof_chunks * g_ddr3_seq.wr_chunksize;
constant c_wr_fifo_depth : natural := sel_a_b(c_blocksize > c_min_fifo_size, c_blocksize, c_min_fifo_size); -- c_blocksize * 2;
constant c_rd_fifo_depth : natural := sel_a_b(c_blocksize > c_min_fifo_size, c_blocksize, c_min_fifo_size); -- c_blocksize * 2;
constant c_total_data_w : natural := g_nof_streams * g_in_dat_w;
constant c_complex_data_w : natural := c_total_data_w * c_nof_complex;
constant c_data_w : natural := sel_a_b(g_use_complex, c_complex_data_w, c_total_data_w);
constant c_nof_ch_in : natural := g_frame_size_in * g_ddr3_seq.rd_chunksize;
constant c_nof_ch_sel : natural := c_nof_ch_in;
constant c_cnt_sop_w : natural := ceil_log2(g_nof_blk_per_sync) + 1;
signal ss_in_sosi : t_dp_sosi;
signal ss_in_siso : t_dp_siso;
-- ctrl & status DDR3 driver
signal dvr_start_addr : t_ddr3_addr;
signal dvr_end_addr : t_ddr3_addr;
signal dvr_en : std_logic;
signal dvr_wr_not_rd : std_logic;
signal dvr_done : std_logic;
signal flush_ena : std_logic;
-- DDR3 controller status
signal ctlr_init_done : std_logic;
signal ctlr_rdy : std_logic;
signal init_done_data_start : std_logic;
signal transpose_in_sosi : t_dp_sosi;
signal transpose_in_siso : t_dp_siso;
signal transpose_out_sosi : t_dp_sosi;
signal block_gen_out_sosi : t_dp_sosi;
signal pipeline_out_sosi : t_dp_sosi;
signal sync_bsn : std_logic_vector(c_dp_stream_bsn_w - 1 downto 0);
signal wr_req : std_logic;
signal rd_req_i : std_logic;
signal rd_dat_i : std_logic_vector(c_dp_stream_bsn_w - 1 downto 0);
signal rd_val_i : std_logic;
signal cnt_sop : std_logic_vector(c_cnt_sop_w - 1 downto 0);
signal nof_sop : std_logic_vector(c_cnt_sop_w - 1 downto 0);
signal i_mon_nof_sop : std_logic_vector(c_cnt_sop_w - 1 downto 0);
signal nxt_mon_nof_sop : std_logic_vector(c_cnt_sop_w - 1 downto 0);
signal sync_ok_in : std_logic;
signal sync_ok_out : std_logic;
begin
g_merge_in_complex : if g_use_complex = true generate
process(snk_in_arr)
begin
ss_in_sosi <= snk_in_arr(0);
for i in 0 to g_nof_streams - 1 loop
ss_in_sosi.data((2 * i + 1) * g_in_dat_w - 1 downto 2 * i * g_in_dat_w) <= snk_in_arr(i).re(g_in_dat_w - 1 downto 0);
ss_in_sosi.data((2 * i + 2) * g_in_dat_w - 1 downto (2 * i + 1) * g_in_dat_w) <= snk_in_arr(i).im(g_in_dat_w - 1 downto 0);
end loop;
end process;
end generate;
-- g_merge_in_data : IF g_use_complex = FALSE GENERATE
-- merge_input : PROCESS(snk_in_arr)
-- BEGIN
-- transpose_in_sosi <= snk_in_arr(0);
-- FOR i IN 0 TO g_nof_streams-1 LOOP
-- transpose_in_sosi.data((i+1)*g_in_dat_w-1 DOWNTO i*g_in_dat_w) <= snk_in_arr(i).data(g_in_dat_w-1 DOWNTO 0);
-- END LOOP;
-- END PROCESS;
-- END GENERATE;
gen_pre_transpose : if g_ena_pre_transp = true generate
u_single_ss : entity ss_lib.ss
generic map (
g_dsp_data_w => c_total_data_w,
g_nof_ch_in => c_nof_ch_in,
g_nof_ch_sel => c_nof_ch_sel,
g_select_file_name => g_select_file,
g_use_complex => false
)
port map (
mm_rst => mm_rst,
mm_clk => mm_clk,
dp_rst => dp_rst,
dp_clk => dp_clk,
-- Memory Mapped
ram_ss_ss_mosi => ram_ss_ss_transp_mosi,
ram_ss_ss_miso => ram_ss_ss_transp_miso,
-- Streaming
input_sosi => ss_in_sosi,
input_siso => ss_in_siso,
output_sosi => transpose_in_sosi,
output_siso => transpose_in_siso
);
end generate;
gen_not_pre_transpose : if g_ena_pre_transp = false generate
transpose_in_sosi <= ss_in_sosi;
ss_in_siso <= transpose_in_siso;
end generate;
g_siso : for J in 0 to g_nof_streams - 1 generate
snk_out_arr(J) <= ss_in_siso;
end generate;
u_ddr3: entity work.ddr3
generic map(
g_ddr => c_ddr3_phy_4g,
g_phy => g_phy,
g_mts => g_mts,
g_wr_data_w => c_data_w,
g_wr_use_ctrl => true,
g_wr_fifo_depth => c_wr_fifo_depth,
g_rd_fifo_depth => c_rd_fifo_depth,
g_rd_data_w => c_data_w,
g_flush_wr_fifo => true,
g_flush_ext_ena => true,
g_flush_sop => true,
g_flush_sop_sync => true,
g_flush_sop_channel => false,
g_flush_sop_start_channel => 0,
g_flush_nof_channels => 0
)
port map (
mm_clk => mm_clk,
mm_rst => mm_rst,
ctlr_ref_clk => dp_ref_clk,
ctlr_rst => dp_ref_rst,
phy_in => phy_in,
phy_io => phy_io,
phy_ou => phy_ou,
ctlr_gen_clk => dp_out_clk,
ctlr_gen_rst => dp_out_rst,
reg_io_ddr_mosi => reg_io_ddr_mosi,
reg_io_ddr_miso => reg_io_ddr_miso,
ctlr_init_done => ctlr_init_done,
ctlr_rdy => ctlr_rdy,
dvr_start_addr => dvr_start_addr,
dvr_end_addr => dvr_end_addr,
dvr_done => dvr_done,
dvr_wr_not_rd => dvr_wr_not_rd,
dvr_en => dvr_en,
wr_clk => dp_clk,
wr_rst => dp_rst,
wr_sosi => transpose_in_sosi,
wr_siso => transpose_in_siso,
flush_ena => flush_ena,
rd_sosi => transpose_out_sosi,
rd_siso => src_in_arr(0),
rd_clk => dp_clk,
rd_rst => dp_rst,
ser_term_ctrl_out => ser_term_ctrl_out,
par_term_ctrl_out => par_term_ctrl_out,
ser_term_ctrl_in => ser_term_ctrl_in,
par_term_ctrl_in => par_term_ctrl_in,
rd_fifo_usedw => open
);
flush_ena <= not(ctlr_init_done) or not(sync_ok_out);
init_done_data_start <= ctlr_init_done and transpose_in_sosi.sync;
u_ddr3_sequencer: entity work.ddr3_seq
generic map(
g_ddr => c_ddr3_phy_4g,
g_ddr3_seq => g_ddr3_seq
)
port map (
dp_rst => dp_rst,
dp_clk => dp_clk,
en_evt => dvr_en,
wr_not_rd => dvr_wr_not_rd,
start_addr => dvr_start_addr,
end_addr => dvr_end_addr,
done => dvr_done,
init_done => init_done_data_start,
ctlr_rdy => ctlr_rdy,
sync_ok_in => sync_ok_in,
sync_ok_out => sync_ok_out
);
u_cnt_sop : entity common_lib.common_counter
generic map (
g_width => c_cnt_sop_w
)
port map (
rst => dp_rst,
clk => dp_clk,
cnt_clr => transpose_in_sosi.sync,
cnt_en => transpose_in_sosi.sop,
count => cnt_sop
);
nof_sop <= INCR_UVEC(cnt_sop, 1); -- +1 because the sop at the sync also counts
nxt_mon_nof_sop <= nof_sop when transpose_in_sosi.sync = '1' else i_mon_nof_sop;
sync_ok_in <= '1' when TO_UINT(i_mon_nof_sop) = g_nof_blk_per_sync and TO_UINT(nof_sop) <= g_nof_blk_per_sync else '0';
p_clk : process(dp_rst, dp_clk)
begin
if dp_rst = '1' then
i_mon_nof_sop <= (others => '0');
elsif rising_edge(dp_clk) then
i_mon_nof_sop <= nxt_mon_nof_sop;
end if;
end process;
---------------------------------------------------------------
-- FIFO FOR SYNC-BSN
---------------------------------------------------------------
wr_req <= snk_in_arr(0).sync and ctlr_init_done;
u_sync_bsn_fifo : entity common_lib.common_fifo_sc
generic map (
g_use_lut => true, -- Make this FIFO in logic, since it's only 2 words deep.
g_dat_w => c_dp_stream_bsn_w,
g_nof_words => 16
)
port map (
rst => dp_rst,
clk => dp_clk,
wr_dat => snk_in_arr(0).bsn,
wr_req => wr_req,
wr_ful => open,
rd_dat => rd_dat_i,
rd_req => rd_req_i,
rd_emp => open,
rd_val => rd_val_i,
usedw => open
);
---------------------------------------------------------------
-- CREATE READ-AHEAD FIFO INTERFACE FOR SYNC-BSN
---------------------------------------------------------------
u_fifo_adapter : entity common_lib.common_fifo_rd
generic map (
g_dat_w => c_dp_stream_bsn_w
)
port map(
rst => dp_rst,
clk => dp_clk,
-- ST sink: RL = 1
fifo_req => rd_req_i,
fifo_dat => rd_dat_i,
fifo_val => rd_val_i,
-- ST source: RL = 0
rd_req => block_gen_out_sosi.sync,
rd_dat => sync_bsn,
rd_val => open
);
-----------------------
-- Pipeline
-----------------------
u_dp_pipeline : entity dp_lib.dp_pipeline
generic map(
g_pipeline => 1
)
port map (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_out => OPEN,
snk_in => transpose_out_sosi,
-- ST source
src_in => OPEN,
src_out => pipeline_out_sosi
);
--------------------
-- DP BLOCK GEN (providing sop/eop)
--------------------
u_dp_block_gen : entity dp_lib.dp_block_gen
generic map(
g_use_src_in => false,
g_nof_data => g_frame_size_out,
g_nof_blk_per_sync => g_nof_blk_per_sync,
g_empty => 0,
g_channel => 0,
g_error => 0
)
port map(
rst => dp_rst,
clk => dp_clk,
snk_in => transpose_out_sosi,
-- Use incoming data to generate more data
src_in => c_dp_siso_rdy,
src_out => block_gen_out_sosi,
en => '1'
);
g_merge_out_complex : if g_use_complex = true generate
gen_merge_out : process(block_gen_out_sosi, pipeline_out_sosi)
begin
for i in 0 to g_nof_streams - 1 loop
src_out_arr(i) <= block_gen_out_sosi;
src_out_arr(i).valid <= pipeline_out_sosi.valid;
src_out_arr(i).re <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2 * i + 1) * g_in_dat_w - 1 downto 2 * i * g_in_dat_w));
src_out_arr(i).im <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2 * i + 2) * g_in_dat_w - 1 downto (2 * i + 1) * g_in_dat_w));
if (block_gen_out_sosi.sync = '1') then
src_out_arr(i).bsn <= sync_bsn;
end if;
end loop;
end process;
end generate;
g_merge_out_data : if g_use_complex = false generate
gen_merge_out : process(block_gen_out_sosi, pipeline_out_sosi)
begin
for i in 0 to g_nof_streams - 1 loop
src_out_arr(i) <= block_gen_out_sosi;
src_out_arr(i).valid <= pipeline_out_sosi.valid;
src_out_arr(i).data <= RESIZE_DP_DATA(pipeline_out_sosi.data((i + 1) * g_in_dat_w - 1 downto i * g_in_dat_w));
if (block_gen_out_sosi.sync = '1') then
src_out_arr(i).bsn <= sync_bsn;
end if;
end loop;
end process;
end generate;
end str;