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

Added pipelining. Improved use of pointer.

parent b854985b
Branches
No related tags found
2 merge requests!148L2SDP-495,!146Prepared dp_bsn_align_v2.vhd (still empty) and mmp_, tb_ and tb_mmp_ files,...
......@@ -54,7 +54,9 @@ ENTITY dp_bsn_align_v2 IS
g_buffer_nof_blocks : NATURAL; -- circular buffer size per input, choose ceil_pow2(1 + g_bsn_latency_max)
g_bsn_w : NATURAL := c_dp_stream_bsn_w; -- number of bits in sosi BSN
g_data_w : NATURAL; -- number of bits in sosi data
g_filler_value : INTEGER := 0 -- output sosi data value for missing input blocks
g_filler_value : INTEGER := 0; -- output sosi data value for missing input blocks
g_pipeline_input : NATURAL := 0; -- >= 0, choose 0 for wires, choose 1 to ease timing closure
g_rd_latency : NATURAL := 1 -- 1 or 2, choose 2 to ease timing closure
);
PORT (
dp_rst : IN STD_LOGIC;
......@@ -100,7 +102,7 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
TYPE t_reg IS RECORD
-- p_write_arr
wr_pointer : NATURAL; -- only for debugging
wr_pointer : NATURAL;
wr_copi_arr : t_mem_copi_arr(g_nof_streams-1 DOWNTO 0);
-- all streams
filled_arr : t_filled_arr(g_nof_streams-1 DOWNTO 0);
......@@ -109,7 +111,7 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
bsn_arr : t_bsn_arr(g_buffer_nof_blocks-1 DOWNTO 0);
mm_sosi : t_dp_sosi;
-- p_read
rd_pointer : NATURAL; -- only for debugging
rd_pointer : INTEGER; -- use integer to detect need to wrap to natural
rd_offset : STD_LOGIC_VECTOR(c_mem_ram.adr_w-1 DOWNTO 0);
rd_copi : t_mem_copi;
END RECORD;
......@@ -124,15 +126,19 @@ ARCHITECTURE rtl OF dp_bsn_align_v2 IS
(OTHERS=>'0'),
c_mem_copi_rst);
-- Local registers
-- State registers
SIGNAL r : t_reg;
SIGNAL nxt_r : t_reg;
-- Pipeline registers
SIGNAL in_sosi_arr_p : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL rd_copi_p : t_mem_copi;
BEGIN
mm_sosi <= r.mm_sosi;
p_clk: PROCESS(dp_clk, dp_rst)
p_reg : PROCESS(dp_clk, dp_rst)
BEGIN
IF dp_rst='1' THEN
r <= c_reg_rst;
......@@ -141,88 +147,84 @@ BEGIN
END IF;
END PROCESS;
p_comb : PROCESS(r, in_sosi_arr, mm_copi)
p_comb : PROCESS(r, in_sosi_arr_p, mm_copi)
-- State variable
VARIABLE v : t_reg;
-- Auxiliary variables
VARIABLE v_ref_sosi : t_dp_sosi;
VARIABLE v_pointer : INTEGER;
VARIABLE v_pointer_slv : STD_LOGIC_VECTOR(c_blk_pointer_w-1 DOWNTO 0);
VARIABLE v_product_slv : STD_LOGIC_VECTOR(c_product_w-1 DOWNTO 0);
BEGIN
v := r;
v.mm_sosi.sop := '0';
v.mm_sosi.eop := '0';
v.mm_sosi.valid := '0';
v.mm_sosi.sync := '0';
v.mm_sosi := func_dp_stream_reset_control(r.mm_sosi);
v.wr_copi_arr := RESET_MEM_COPI_CTRL(r.wr_copi_arr);
-- p_write_arr
FOR I IN 0 TO g_nof_streams-1 LOOP
-- p_write
IF in_sosi_arr(I).valid = '1' THEN
-- Increment address or start at block
IF in_sosi_arr_p(I).valid = '1' THEN
-- . increment address during block
v.wr_copi_arr(I).address := RESIZE_MEM_ADDRESS(INCR_UVEC(r.wr_copi_arr(I).address(c_mem_ram.adr_w-1 DOWNTO 0), 1));
IF in_sosi_arr(I).sop = '1' THEN
v_pointer_slv := in_sosi_arr(I).bsn(c_blk_pointer_w-1 DOWNTO 0);
v_product_slv := STD_LOGIC_VECTOR(UNSIGNED(v_pointer_slv) * UNSIGNED(c_block_size_slv));
v.wr_copi_arr(I).address := RESIZE_MEM_ADDRESS(v_product_slv);
END IF;
v.wr_copi_arr(I).wr := '1';
v.wr_copi_arr(I).wrdata := RESIZE_MEM_SDATA(in_sosi_arr(I).data);
v.wr_copi_arr(I).wrdata := RESIZE_MEM_SDATA(in_sosi_arr_p(I).data);
END IF;
-- Set filled flag
v_pointer := TO_UINT(v_pointer_slv);
IF in_sosi_arr(I).sop = '1' THEN -- at sop, so assume rest will follow in time
v.filled_arr(I)(v_pointer) := '1';
END IF;
IF in_sosi_arr_p(I).sop = '1' THEN
-- . set address at start of block
v_pointer_slv := in_sosi_arr_p(I).bsn(c_blk_pointer_w-1 DOWNTO 0);
v_product_slv := MULT_UVEC(v_pointer_slv, c_block_size_slv);
v.wr_copi_arr(I).address := RESIZE_MEM_ADDRESS(v_product_slv);
-- . set filled flag at sop, so assume rest of block will follow in time
v.filled_arr(I)(TO_UINT(v_pointer_slv)) := '1';
END IF;
END LOOP;
-- p_control, all at local reference input 0 sop
v_ref_sosi := in_sosi_arr(0);
v_ref_sosi := in_sosi_arr_p(0);
IF v_ref_sosi.sop = '1' THEN
-- . write sync & bsn buffer
v_pointer := TO_UINT(v_ref_sosi.bsn(c_blk_pointer_w-1 DOWNTO 0));
v.sync_arr(v_pointer) := v_ref_sosi.sync;
v.bsn_arr(v_pointer) := v_ref_sosi.bsn(g_bsn_w-1 DOWNTO 0);
v.wr_pointer := v_pointer;
-- . update read pointer at g_bsn_latency_max blocks behind the reference write pointer
v_pointer := v_pointer - g_bsn_latency_max;
IF v_pointer < 0 THEN
v_pointer := v_pointer + g_buffer_nof_blocks;
v.wr_pointer := TO_UINT(v_ref_sosi.bsn(c_blk_pointer_w-1 DOWNTO 0));
v.sync_arr(v.wr_pointer) := v_ref_sosi.sync;
v.bsn_arr(v.wr_pointer) := v_ref_sosi.bsn(g_bsn_w-1 DOWNTO 0);
-- . update read block pointer at g_bsn_latency_max blocks behind the reference write pointer
v.rd_pointer := v.wr_pointer - g_bsn_latency_max;
IF v.rd_pointer < 0 THEN
v.rd_pointer := v.rd_pointer + g_buffer_nof_blocks;
END IF;
v.rd_pointer := v_pointer;
-- . update read address
v_pointer_slv := TO_UVEC(v_pointer, c_blk_pointer_w);
v_product_slv := STD_LOGIC_VECTOR(UNSIGNED(v_pointer_slv) * UNSIGNED(c_block_size_slv));
-- . update read address of read block pointer
v_pointer_slv := TO_UVEC(v.rd_pointer, c_blk_pointer_w);
v_product_slv := MULT_UVEC(v_pointer_slv, c_block_size_slv);
v.rd_offset := RESIZE_UVEC(v_product_slv, c_mem_ram.adr_w);
-- . issue mm_sosi, if there is output ready to be read, indicated by filled reference block
IF r.filled_arr(0)(v_pointer) = '1' THEN
IF r.filled_arr(0)(v.rd_pointer) = '1' THEN
v.mm_sosi.sop := '1';
v.mm_sosi.eop := '1';
v.mm_sosi.valid := '1';
-- . pass on timestamp information
v.mm_sosi.sync := v.sync_arr(v_pointer);
v.mm_sosi.bsn := v.bsn_arr(v_pointer);
v.mm_sosi.sync := v.sync_arr(v.rd_pointer);
v.mm_sosi.bsn := v.bsn_arr(v.rd_pointer);
-- . use channel field to pass on filled flags
FOR I IN 0 TO g_nof_streams-1 LOOP
v.mm_sosi.channel(I) := v.filled_arr(I)(v_pointer);
v.mm_sosi.channel(I) := v.filled_arr(I)(v.rd_pointer);
END LOOP;
END IF;
-- . clear filled flags, after mm_sosi was issued, or could have been issued
FOR I IN 0 TO g_nof_streams-1 LOOP
v.filled_arr(I)(v_pointer) := '0';
v.filled_arr(I)(v.rd_pointer) := '0';
END LOOP;
END IF;
-- p_read
v.rd_copi := mm_copi;
v.rd_copi.address := RESIZE_MEM_ADDRESS(ADD_UVEC(r.rd_offset, mm_copi.address)); -- sum yields c_mem_ram.adr_w bits, because left operand determines width
-- next state
nxt_r <= v;
END PROCESS;
......@@ -237,11 +239,29 @@ BEGIN
wr_en => r.wr_copi_arr(I).wr,
wr_adr => r.wr_copi_arr(I).address(c_ram_buf.adr_w-1 DOWNTO 0),
wr_dat => r.wr_copi_arr(I).wrdata(c_ram_buf.dat_w-1 DOWNTO 0),
rd_en => nxt_r.rd_copi.rd,
rd_adr => nxt_r.rd_copi.address(c_ram_buf.adr_w-1 DOWNTO 0), -- use nxt_r to not increase the rd latency
rd_en => rd_copi_p.rd,
rd_adr => rd_copi_p.address(c_ram_buf.adr_w-1 DOWNTO 0),
rd_dat => mm_cipo_arr(I).rddata(c_ram_buf.dat_w-1 DOWNTO 0),
rd_val => mm_cipo_arr(I).rdval
);
END GENERATE;
-- Pipelining
u_in_sosi_arr_p : ENTITY work.dp_pipeline_arr
GENERIC MAP (
g_nof_streams => g_nof_streams,
g_pipeline => g_pipeline_input -- 0 for wires, > 0 for registers,
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
-- ST sink
snk_in_arr => in_sosi_arr,
-- ST source
src_out_arr => in_sosi_arr_p
);
rd_copi_p <= nxt_r.rd_copi WHEN g_rd_latency = 1 ELSE r.rd_copi;
END rtl;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment