Commit 9493361e authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wrsw_swcore: new async mem: initial commit

parent 4442e57e
files = ["swc_async_grow_fifo.vhd",
"swc_async_fifo_ctrl.vhd",
"swc_fifo_mem_cell.vhd",
"swc_async_shrink_fifo.vhd",
"swc_private_pkg.vhd",
"swc_pipelined_mux.vhd",
"swc_async_multiport_mem.vhd"]
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all; -- for f_log2_size
entity swc_async_grow_fifo is
generic (
g_width : integer;
g_ratio : integer;
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
we_i : in std_logic;
d_i : in std_logic_vector(g_width-1 downto 0);
rd_i : in std_logic;
q_o : out std_logic_vector(g_width * g_ratio-1 downto 0);
wr_full_o : out std_logic;
rd_empty_o : out std_logic);
end swc_async_grow_fifo;
architecture rtl of swc_async_grow_fifo is
component swc_fifo_mem_cell
generic (
g_width : integer;
g_size : integer);
port (
clk_i : in std_logic;
wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
wd_i : in std_logic_vector(g_width-1 downto 0);
we_i : in std_logic;
ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_o : out std_logic_vector(g_width-1 downto 0));
end component;
component swc_async_fifo_ctrl
generic (
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
rd_i : in std_logic;
wr_i : in std_logic;
wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end component;
signal wr_sreg : std_logic_vector(g_ratio-1 downto 0);
signal wr_cell : std_logic_vector(g_ratio-1 downto 0);
signal real_we : std_logic;
signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0);
signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0);
begin -- rtl
gen_mem_cells : for i in 0 to g_ratio-1 generate
wr_cell(i) <= we_i and wr_sreg(i);
U_Mem : swc_fifo_mem_cell
generic map (
g_width => g_width * g_ratio,
g_size => g_size)
port map (
clk_i => clk_wr_i,
wa_i => wr_addr,
wd_i => d_i,
we_i => rd_addr,
ra_i => std_logic_vector(rd_ptr),
rd_o => q_int(g_width*(i+1) -1 downto g_width*i));
end generate gen_mem_cells;
p_write_grow_sreg : process(clk_wr_i, rst_n_i)
begin
if rst_n_i = '0' then
wr_sreg(0) <= '1';
wr_sreg(wr_sreg'left downto 1) <= (others => '0');
real_we <= '0';
elsif rising_edge(clk_wr_i) then
if(we_i = '1') then
wr_sreg <= wr_sreg(wr_sreg'left-1 downto 0) & wr_sreg(wr_sreg'left);
if(wr_sreg(wr_sreg'left) = '1' and full_int = '0') then
real_we <= '1';
else
real_we <= '0';
end if;
else
real_we <= '0';
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
entity swc_async_fifo_ctrl is
generic (
g_size : integer);
port(
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
rd_i : in std_logic;
wr_i : in std_logic;
wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end swc_async_fifo_ctrl;
architecture rtl of swc_async_fifo_ctrl is
function f_gray_inc(x : unsigned) return unsigned is
variable bin, tmp : unsigned(x'left downto 0);
begin
-- gray to binary
for i in 0 to x'left loop
bin(i) := '0';
for j in i to x'left loop
bin(i) := bin(i) xor x(j);
end loop; -- j
end loop; -- i
-- increase
tmp := bin + 1;
-- binary to gray
return tmp(tmp'left) & (tmp(tmp'left-1 downto 0) xor tmp(tmp'left downto 1));
end f_gray_inc;
signal wr_ptr, rd_ptr : unsigned(f_log2_size(g_size) -1 downto 0);
signal full_int, empty_int : std_logic;
signal same_addr : std_logic;
signal rst_stat, set_stat : std_logic;
signal set_full, set_empty : std_logic;
signal stat : std_logic;
begin -- rtl
p_write_ptr : process(clk_wr_i, rst_n_i)
begin
if rst_n_i = '0' then
wr_ptr <= (others => '0');
elsif rising_edge(clk_wr_i) then
if(wr_i = '1' and full_int = '0') then
wr_ptr <= f_gray_inc(wr_ptr);
end if;
end if;
end process;
p_read_ptr : process(clk_rd_i, rst_n_i)
begin
if rst_n_i = '0' then
rd_ptr <= (others => '0');
elsif rising_edge(clk_rd_i) then
if(rd_i = '1' and empty_int = '0') then
rd_ptr <= f_gray_inc(rd_ptr);
end if;
end if;
end process;
p_quardant_status : process(rd_ptr, wr_ptr)
begin
set_stat <= (wr_ptr(wr_ptr'left-1) xnor rd_ptr(rd_ptr'left))
and (wr_ptr(wr_ptr'left) xor rd_ptr(rd_ptr'left-1));
rst_stat <= (wr_ptr(wr_ptr'left-1) xor rd_ptr(rd_ptr'left))
and (wr_ptr(wr_ptr'left) xnor rd_ptr(rd_ptr'left-1));
end process;
process(set_stat, rst_stat, rst_n_i)
begin
if(rst_stat = '1' or rst_n_i = '0') then
stat <= '0';
elsif(set_stat = '1') then
stat <= '1';
end if;
end process;
set_full <= '1' when (stat = '1' and wr_ptr = rd_ptr) else '0';
set_empty <= '1' when (stat = '0' and wr_ptr = rd_ptr) else '0';
p_full_flag : process(clk_wr_i, set_full)
begin
if(set_full = '1') then
full_int <= '1';
elsif rising_edge(clk_wr_i) then
full_int <= set_full;
end if;
end process;
p_empty_flag : process(clk_rd_i, set_empty)
begin
if(set_empty = '1') then
empty_int <= '1';
elsif rising_edge(clk_rd_i) then
empty_int <= set_empty;
end if;
end process;
full_o <= full_int;
empty_o <= empty_int;
wr_addr_o <= std_logic_vector(wr_ptr);
rd_addr_o <= std_logic_vector(rd_ptr);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all; -- for f_log2_size
entity swc_async_grow_fifo is
generic (
g_width : integer := 16;
g_ratio : integer := 6;
g_size : integer := 8);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
we_i : in std_logic;
align_i : in std_logic; -- 1: aligned write
d_i : in std_logic_vector(g_width-1 downto 0);
rd_i : in std_logic;
q_o : out std_logic_vector(g_width * g_ratio-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end swc_async_grow_fifo;
architecture rtl of swc_async_grow_fifo is
component swc_fifo_mem_cell
generic (
g_width : integer;
g_size : integer);
port (
clk_i : in std_logic;
wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
wd_i : in std_logic_vector(g_width-1 downto 0);
we_i : in std_logic;
ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_o : out std_logic_vector(g_width-1 downto 0));
end component;
component swc_async_fifo_ctrl
generic (
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
rd_i : in std_logic;
wr_i : in std_logic;
wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end component;
signal wr_sreg : std_logic_vector(g_ratio-1 downto 0);
signal wr_cell : std_logic_vector(g_ratio-1 downto 0);
signal real_we : std_logic;
signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0);
signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0);
signal full_int : std_logic;
begin -- rtl
gen_mem_cells : for i in 0 to g_ratio-1 generate
wr_cell(i) <= wr_sreg(i) and we_i;
U_Mem : swc_fifo_mem_cell
generic map (
g_width => g_width,
g_size => g_size)
port map (
clk_i => clk_wr_i,
wa_i => wr_addr,
wd_i => d_i,
we_i => wr_cell(i),
ra_i => rd_addr,
rd_o => q_int(g_width*(i+1) -1 downto g_width*i));
end generate gen_mem_cells;
U_CTRL : swc_async_fifo_ctrl
generic map (
g_size => g_size)
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_wr_i,
clk_rd_i => clk_rd_i,
rd_i => rd_i,
wr_i => real_we,
wr_addr_o => wr_addr,
rd_addr_o => rd_addr,
full_o => full_int,
empty_o => empty_o);
p_write_grow_sreg : process(clk_wr_i, rst_n_i)
begin
if rst_n_i = '0' then
wr_sreg(0) <= '1';
wr_sreg(wr_sreg'left downto 1) <= (others => '0');
elsif rising_edge(clk_wr_i) then
if(we_i = '1') then
if(align_i = '1') then
wr_sreg(0) <= '1';
wr_sreg(wr_sreg'left downto 1) <= (others => '0');
else
wr_sreg <= wr_sreg(wr_sreg'left-1 downto 0) & wr_sreg(wr_sreg'left);
end if;
end if;
end if;
end process;
real_we <= wr_cell(wr_cell'left);
p_output_reg : process(clk_rd_i, rst_n_i)
begin
if (rst_n_i = '0') then
q_o <= (others => '0');
elsif rising_edge(clk_rd_i) then
if(rd_i = '1') then
q_o <= q_int;
end if;
end if;
end process;
full_o <= full_int and wr_sreg(wr_sreg'left);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.swc_private_pkg.all;
use work.genram_pkg.all;
entity swc_async_multiport_mem is
generic (
g_ratio : integer;
g_page_size : integer;
g_num_pages : integer;
g_num_ports : integer
);
port(
-- I/O ports clock (slow)
clk_io_i : in std_logic;
-- Memory/Core clock (fast)
clk_core_i : in std_logic;
rst_n_i : in std_logic;
-- read-write ports I/F (streaming)
wport_i : in t_mpm_write_in_array(0 to g_num_ports-1);
wport_o : out t_mpm_write_out_array(0 to g_num_ports-1);
rport_i : in t_mpm_read_in_array(0 to g_num_ports-1);
rport_o : out t_mpm_read_out_array(0 to g_num_ports-1);
-- linked list I/F
ll_addr_o : out std_logic_vector(f_log2_size(g_num_pages)-1 downto 0);
ll_data_o : out std_logic_vector(f_log2_size(g_num_pages)-1 downto 0);
ll_data_i : in std_logic_vector(f_log2_size(g_num_pages)-1 downto 0);
ll_we_o : out std_logic
);
end swc_async_multiport_mem;
architecture rtl of swc_async_multiport_mem is
component swc_async_grow_fifo
generic (
g_width : integer;
g_ratio : integer;
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
align_i : in std_logic;
we_i : in std_logic;
d_i : in std_logic_vector(g_width-1 downto 0);
rd_i : in std_logic;
q_o : out std_logic_vector(g_width * g_ratio-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end component;
type t_fifo_slv_array is array(0 to g_num_ports-1) of std_logic_vector(c_data_path_width downto 0);
type t_wport_state is record
cur_page : unsigned(c_page_addr_width-1 downto 0);
cur_offset : unsigned(f_log2_size(g_page_size)-1 downto 0);
cur_valid : std_logic;
next_page : unsigned(c_page_addr_width-1 downto 0);
next_offset : unsigned(f_log2_size(g_page_size)-1 downto 0);
next_valid : std_logic;
fifo_empty : std_logic;
fifo_full : std_logic;
fifo_nempty : std_logic;
fifo_rd : std_logic;
fifo_q : std_logic_vector((c_data_path_width+1) * g_ratio - 1 downto 0);
end record;
type t_wport_state_array is array(0 to g_num_ports-1) of t_wport_state;
signal w_req, w_sel, w_mask : std_logic_vector(f_log2_size(g_num_ports)-1 downto 0);
signal wstate : t_wport_state_array;
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
signal grant : out std_logic_vector)is
variable reqs : std_logic_vector(g_width - 1 downto 0);
variable gnts : std_logic_vector(g_width - 1 downto 0);
variable gnt : std_logic_vector(g_width - 1 downto 0);
variable gntM : std_logic_vector(g_width - 1 downto 0);
variable zeros : std_logic_vector(g_width - 1 downto 0);
begin
zeros := (others => '0');
-- bit twiddling magic :
s_gnt := req and std_logic_vector(unsigned(not req) + 1);
s_reqs := req and not (std_logic_vector(unsigned(pre_grant) - 1) or pre_grant);
s_gnts := reqs and std_logic_vector(unsigned(not reqs)+1);
s_gntM := gnt when reqs = zeros else gnts;
if((req and pre_grant) = s_zeros) then
grant <= gntM;
s_pre_grant <= gntM; -- remember current grant vector, for the next operation
end if;
end f_rr_arbitrate;
begin -- rtl
gen_input_fifos : for i in 0 to g_num_ports-1 generate
U_Input_FIFOx : swc_async_grow_fifo
generic map (
g_width => c_data_path_width + 1,
g_ratio => g_ratio,
g_size => c_mpm_async_fifo_depth)
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_io_i,
clk_rd_i => clk_core_i,
we_i => wport_i(i).d_valid,
d_i(c_data_path_width-2 downto 0) => wport_i(i).d,
d_i(c_data_path_width-1) => wport_i(i).d_eof,
align_i => wport_i(i).d_eof,
rd_i => wstate(i).fifo_rd,
q_o => wstate(i).fifo_q,
full_o => wstate(i).fifo_full,
empty_o => wstate(i).fifo_empty);
end generate gen_input_fifos;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all; -- for f_log2_size
entity swc_async_shrink_fifo is
generic (
g_width : integer; -- narrow port width
g_ratio : integer;
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
we_i : in std_logic;
d_i : in std_logic_vector(g_width*g_ratio-1 downto 0);
rd_i : in std_logic;
q_o : out std_logic_vector(g_width-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end swc_async_shrink_fifo;
architecture rtl of swc_async_shrink_fifo is
component swc_fifo_mem_cell
generic (
g_width : integer;
g_size : integer);
port (
clk_i : in std_logic;
wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
wd_i : in std_logic_vector(g_width-1 downto 0);
we_i : in std_logic;
ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_o : out std_logic_vector(g_width-1 downto 0));
end component;
component swc_async_fifo_ctrl
generic (
g_size : integer);
port (
rst_n_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
rd_i : in std_logic;
wr_i : in std_logic;
wr_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_addr_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0);
full_o : out std_logic;
empty_o : out std_logic);
end component;
signal rd_count : unsigned(3 downto 0);
signal real_rd : std_logic;
signal q_int : std_logic_vector(g_width*g_ratio-1 downto 0);
signal wr_addr, rd_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0);
signal empty_int : std_logic;
signal line_flushed : std_logic;
begin -- rtl
gen_mem_cells : for i in 0 to g_ratio-1 generate
U_Mem : swc_fifo_mem_cell
generic map (
g_width => g_width,
g_size => g_size)
port map (
clk_i => clk_wr_i,
wa_i => wr_addr,
wd_i => d_i(g_width*(i+1) -1 downto g_width*i),
we_i => we_i,
ra_i => rd_addr,
rd_o => q_int(g_width*(i+1) -1 downto g_width*i));
end generate gen_mem_cells;
U_CTRL : swc_async_fifo_ctrl
generic map (
g_size => g_size)
port map (
rst_n_i => rst_n_i,
clk_wr_i => clk_wr_i,
clk_rd_i => clk_rd_i,
rd_i => real_rd,
wr_i => we_i,
wr_addr_o => wr_addr,
rd_addr_o => rd_addr,
full_o => full_o,
empty_o => empty_int);
p_read_mux : process(clk_rd_i, rst_n_i)
begin
if rst_n_i = '0' then
rd_count <= (others => '0');
q_o <= (others => '0');
elsif rising_edge(clk_rd_i) then
if(rd_i = '1' and empty_int = '0') then
if(rd_count = g_ratio-1) then
rd_count <= (others => '0');
else
rd_count <= rd_count + 1;
end if;
q_o <= q_int(((to_integer(rd_count)+1)*g_width)-1 downto to_integer(rd_count)*g_width);
end if;
end if;
end process;
line_flushed <= '1' when (rd_count = g_ratio-1) else '0';
real_rd <= line_flushed and rd_i;
empty_o <= empty_int and line_flushed;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.genram_pkg.all;
entity swc_fifo_mem_cell is
generic (
g_width : integer;
g_size : integer);
port (
clk_i : in std_logic;
wa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
wd_i : in std_logic_vector(g_width-1 downto 0);
we_i : in std_logic;
ra_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0);
rd_o : out std_logic_vector(g_width-1 downto 0));
end swc_fifo_mem_cell;
architecture rtl of swc_fifo_mem_cell is
type t_mem_array is array(0 to g_size-1) of std_logic_vector(g_width-1 downto 0);
signal mem : t_mem_array;
begin -- rtl
rd_o <= mem(to_integer(unsigned(ra_i)));
p_write : process(clk_i)
begin
if rising_edge(clk_i) then
if(we_i = '1') then
mem(to_integer(unsigned(wa_i))) <= wd_i;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
package swc_private_pkg is
constant c_data_path_width : integer := 18;
constant c_eof_marker : std_logic_vector(c_data_path_width-1 downto 0) := "11XXXXXXXXXXXXXXXX";
constant c_mpm_async_fifo_depth : integer := 8;
constant c_page_addr_width : integer := 12;
type t_generic_slv_array is array (integer range <>, integer range <>) of std_logic;
type t_mpm_write_in is record
d : std_logic_vector(c_data_path_width-1 downto 0);
d_valid : std_logic;
d_eof : std_logic;
pg_addr : std_logic_vector(c_page_addr_width-1 downto 0);
pg_valid : std_logic;
end record;
type t_mpm_write_out is record
d_req : std_logic;
pg_req : std_logic;
end record;
type t_mpm_write_in_array is array (integer range <>) of t_mpm_write_in;
type t_mpm_write_out_array is array (integer range <>) of t_mpm_write_out;
type t_mpm_read_out is record
d : std_logic_vector(c_data_path_width-1 downto 0);
d_valid : std_logic;
d_eof : std_logic;
pg_req : std_logic;
end record;
type t_mpm_read_in is record
pg_addr : std_logic_vector(c_page_addr_width-1 downto 0);
pg_valid : std_logic;
d_req : std_logic;
end record;
type t_mpm_read_in_array is array (integer range <>) of t_mpm_read_in;
type t_mpm_read_out_array is array (integer range <>) of t_mpm_read_out;
end swc_private_pkg;
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment