From 68dda3e8749a49482720eb534d18cb2fc050e370 Mon Sep 17 00:00:00 2001 From: Grzegorz Daniluk <grzegorz.daniluk@cern.ch> Date: Wed, 31 Aug 2016 23:32:24 +0200 Subject: [PATCH] swcore: swc_ll_read_data_validate supports generic number of write interfaces --- .../swc_ll_read_data_validation.vhd | 111 +++++++++++------- modules/wrsw_swcore/swc_swcore_pkg.vhd | 12 +- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/modules/wrsw_swcore/swc_ll_read_data_validation.vhd b/modules/wrsw_swcore/swc_ll_read_data_validation.vhd index 620d82c8..7e72376c 100644 --- a/modules/wrsw_swcore/swc_ll_read_data_validation.vhd +++ b/modules/wrsw_swcore/swc_ll_read_data_validation.vhd @@ -3,10 +3,10 @@ -- Project : WhiteRabbit switch ------------------------------------------------------------------------------- -- File : swc_ll_read_data_validation.vhd --- Author : Maciej Lipinski +-- Author : Maciej Lipinski, Grzegorz Daniluk -- Company : CERN BE-Co-HT -- Created : 2012-01-30 --- Last update: 2012-01-30 +-- Last update: 2016-08-31 -- Platform : FPGA-generic -- Standard : VHDL'87 ------------------------------------------------------------------------------- @@ -23,7 +23,7 @@ -- can overtake the writting process. ------------------------------------------------------------------------------- -- --- Copyright (c) 2012 CERN / BE-CO-HT +-- Copyright (c) 2012-2016 CERN / BE-CO-HT -- -- This source file is free software; you can redistribute it -- and/or modify it under the terms of the GNU Lesser General @@ -51,16 +51,19 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +use ieee.std_logic_misc.all; library work; use work.swc_swcore_pkg.all; use work.genram_pkg.all; +use work.gencores_pkg.all; entity swc_ll_read_data_validation is generic( - g_addr_width : integer ;--:= c_swc_page_addr_width; - g_data_width : integer --:= c_swc_page_addr_width + g_addr_width : integer; + g_data_width : integer; + g_wports : integer ); port( clk_i : in std_logic; @@ -80,10 +83,9 @@ entity swc_ll_read_data_validation is read_data_ready_i : in std_logic; -- data being written to DPRAM - write_addr_i : in std_logic_vector(g_addr_width - 1 downto 0); - write_data_i : in std_logic_vector(g_data_width - 1 downto 0); - write_data_valid_i : in std_logic; - write_data_ready_i : in std_logic; + write_addr_i : in t_lladr_array(g_wports-1 downto 0); + write_data_i : in t_lldat_array(g_wports-1 downto 0); + write_data_ready_i : in std_logic_vector(g_wports-1 downto 0); -- data read from multiport_linked_list module read_data_o : out std_logic_vector(g_data_width - 1 downto 0); @@ -94,25 +96,46 @@ entity swc_ll_read_data_validation is architecture syn of swc_ll_read_data_validation is - signal valid_data_read : std_logic; -- data read from the DPRAM is valid (page address written) - signal nonvalid_data_read : std_logic; -- data in DPRAM is not valid (the page is being written to) - signal valid_data_write : std_logic; -- valid data is being written to the address we are hooked to - signal valid_data_write_d0 : std_logic; + signal dpram_read_valid : std_logic; -- data read from the DPRAM is valid (page address written) + signal dpram_read_invalid : std_logic; -- data in DPRAM is not valid (the page is being written to) + signal dpram_write_match : std_logic_vector(g_wports-1 downto 0); -- valid data is being written to the address we are hooked to signal wait_valid_data_write : std_logic; -- HIGH after a non-valid data was read, signal mask_read_req : std_logic; -- masks the request to the RR Rabiter which governs -- the access to DPRAM - signal write_data_d0 : std_logic_vector(g_data_width - 1 downto 0); + signal write_data_muxed_d0 : std_logic_vector(g_data_width - 1 downto 0); + signal read_data_valid : std_logic; + signal write_valid_in : std_logic_vector(g_wports-1 downto 0); + signal write_data_muxed : std_logic_vector(g_data_width-1 downto 0); + signal match_if_idx : integer range 0 to g_wports-1; + signal got_valid_match : std_logic; + signal got_valid_match_d0 : std_logic; + signal read_data_out : std_logic_vector(g_data_width - 1 downto 0); + signal nonvalid_data_reg : std_logic; begin + ----------------------------- + -- READ signals -- + ----------------------------- -- the data being read from the Linked List DPRAM is valid,so we just need to pass it - valid_data_read <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '1') else '0'; + dpram_read_valid <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '1') else '0'; -- the data being read from the Linked List DPRAM is not valid (it means that data is still -- being written under the indicated address), this is the case for this module - nonvalid_data_read <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '0') else '0'; + dpram_read_invalid <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '0') else '0'; - -- the data being written to the Linked List DPRAM is what we are wating for and it's valid. - valid_data_write <= '1' when (read_addr_i = write_addr_i and write_data_valid_i = '1' and write_data_ready_i = '1') else '0'; + ----------------------------- + -- WRITE signals -- + ----------------------------- + GEN_WR_SIGS: for I in 0 to g_wports-1 generate + -- check if written data is valid + write_valid_in(I) <= write_data_i(I)(g_data_width-1) and write_data_ready_i(I); + -- the data being written to the Linked List DPRAM is what we are wating for and it's valid. + dpram_write_match(I) <= '1' when (read_addr_i = write_addr_i(I) and write_valid_in(I) = '1') else + '0'; + end generate; + got_valid_match <= or_reduce(dpram_write_match); + match_if_idx <= to_integer(unsigned(f_onehot_decode(dpram_write_match, g_wports))); + write_data_muxed <= write_data_i(match_if_idx); process(clk_i) begin @@ -121,26 +144,25 @@ begin wait_valid_data_write <= '0'; mask_read_req <= '1'; - valid_data_write_d0 <= '0'; - write_data_d0 <= (others =>'0' ); + got_valid_match_d0 <= '0'; + write_data_muxed_d0 <= (others =>'0' ); else - write_data_d0 <= write_data_i; - valid_data_write_d0 <= valid_data_write; + write_data_muxed_d0 <= write_data_muxed; + got_valid_match_d0 <= got_valid_match; - if(nonvalid_data_read = '1' and - valid_data_write = '0' and valid_data_write_d0 = '0') then -- suppress the request, so we don't waste - mask_read_req <= '0'; -- access time to the DPRAM - elsif(valid_data_write = '1' or - valid_data_write = '1' or valid_data_write_d0 = '1') then -- at this point, the request (read_req_i) to + if(dpram_read_invalid = '1' and + got_valid_match = '0' and got_valid_match_d0 = '0') then -- suppress the request, so we don't waste + mask_read_req <= '0'; -- access time to the DPRAM + elsif(got_valid_match = '1' or got_valid_match_d0 = '1') then -- at this point, the request (read_req_i) to mask_read_req <= '1'; -- the LL should finish, and we get read for new request end if; - if(nonvalid_data_read = '1' and -- non-valid data was read *and* - valid_data_write = '0' and valid_data_write_d0 = '0') then -- the same time (or 1-cyc- before -- this is a write gap) + if(dpram_read_invalid = '1' and -- non-valid data was read *and* + got_valid_match = '0' and got_valid_match_d0 = '0') then -- the same time (or 1-cyc- before -- this is a write gap) wait_valid_data_write <= '1'; -- there was no write to the address which is of interest - elsif(valid_data_write = '1') then -- so we need to wait for the proper write + elsif(got_valid_match = '1') then -- so we need to wait for the proper write wait_valid_data_write <= '0'; end if; @@ -149,20 +171,25 @@ begin end process; - read_data_o <= read_data_i when (valid_data_read = '1' ) else -- normal case, the data being read is valid - write_data_i when (valid_data_write = '1' and -- the data being written is valid *and* - (wait_valid_data_write ='1' or nonvalid_data_read = '1' )) else -- we are waiting for valid dta at that address *or* - -- we are just reading non-valid data - write_data_d0 when (valid_data_write_d0 = '1' and -- there is a 1-cycle gap between writing/reading data *and* - (wait_valid_data_write ='1' or nonvalid_data_read = '1' )) else -- we are waiting for valid dta at that address *or* - -- we are just reading non-valid data - + read_data_out <= -- normal case, the data being read is valid + read_data_i when (dpram_read_valid = '1' ) else + -- the data being written is valid *and* + -- we are waiting for valid dta at that address *or* we are just reading non-valid data + write_data_muxed when (got_valid_match = '1' and + (wait_valid_data_write ='1' or dpram_read_invalid = '1' )) else + -- there is a 1-cycle gap between writing/reading data *and* + -- we are waiting for valid dta at that address *or* we are just reading non-valid data + write_data_muxed_d0 when (got_valid_match_d0 = '1' and + (wait_valid_data_write ='1' or dpram_read_invalid = '1' )) else read_data_i; - read_data_valid_o <= (valid_data_read or -- normal case - (valid_data_write and (wait_valid_data_write or nonvalid_data_read)) or - (valid_data_write_d0 and (wait_valid_data_write or nonvalid_data_read)) ) and -- reading data from LL input + read_data_o <= read_data_out; + + read_data_valid <= (dpram_read_valid or -- normal case + (got_valid_match and (wait_valid_data_write or dpram_read_invalid)) or + (got_valid_match_d0 and (wait_valid_data_write or dpram_read_invalid)) ) and -- reading data from LL input read_req_i; -- no request, no answer :) - read_req_o <= mask_read_req and read_req_i; + read_data_valid_o <= read_data_valid; + read_req_o <= mask_read_req and read_req_i; end syn; diff --git a/modules/wrsw_swcore/swc_swcore_pkg.vhd b/modules/wrsw_swcore/swc_swcore_pkg.vhd index 313db950..10e04cb6 100644 --- a/modules/wrsw_swcore/swc_swcore_pkg.vhd +++ b/modules/wrsw_swcore/swc_swcore_pkg.vhd @@ -749,8 +749,9 @@ component swc_multiport_pck_pg_free_module is component swc_ll_read_data_validation is generic( - g_addr_width : integer ;--:= c_swc_page_addr_width; - g_data_width : integer --:= c_swc_page_addr_width + g_addr_width : integer;--:= c_swc_page_addr_width; + g_data_width : integer;--:= c_swc_page_addr_width + g_wports : integer ); port( clk_i : in std_logic; @@ -763,10 +764,9 @@ component swc_multiport_pck_pg_free_module is read_data_valid_i : in std_logic; read_data_ready_i : in std_logic; - write_addr_i : in std_logic_vector(g_addr_width - 1 downto 0); - write_data_i : in std_logic_vector(g_data_width - 1 downto 0); - write_data_valid_i : in std_logic; - write_data_ready_i : in std_logic; + write_addr_i : in t_lladr_array(g_wports-1 downto 0); + write_data_i : in t_lldat_array(g_wports-1 downto 0); + write_data_ready_i : in std_logic_vector(g_wports-1 downto 0); read_data_o : out std_logic_vector(g_data_width - 1 downto 0); read_data_valid_o : out std_logic -- GitLab