-
Notifications
You must be signed in to change notification settings - Fork 0
/
generic_shiftreg_fifo.vhd
168 lines (145 loc) · 6.71 KB
/
generic_shiftreg_fifo.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
----------------------------------------------------------------------------
---- ----
---- ----
---- This file is part of the srl_fifo project ----
---- http://www.opencores.org/cores/srl_fifo ----
---- ----
---- Description ----
---- Implementation of srl_fifo IP core according to ----
---- srl_fifo IP core specification document. ----
---- ----
---- To Do: ----
---- NA ----
---- ----
---- Author(s): ----
---- Andrew Mulcock, amulcock@opencores.org ----
---- ----
---- Modified for WR Project by Tomasz Wlostowski ----
----------------------------------------------------------------------------
---- ----
---- Copyright (C) 2008 Authors and OPENCORES.ORG ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer. ----
---- ----
---- This source file is free software; you can redistribute it ----
---- and/or modify it under the terms of the GNU Lesser General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.1 of the License, or (at your option) any ----
---- later version. ----
---- ----
---- This source 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 Lesser General Public License for more ----
---- details. ----
---- ----
---- You should have received a copy of the GNU Lesser General ----
---- Public License along with this source; if not, download it ----
---- from http://www.opencores.org/lgpl.shtml ----
---- ----
----------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
use work.genram_pkg.all;
entity generic_shiftreg_fifo is
generic (
g_data_width : integer := 128;
g_size : integer := 32
);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
d_i : in std_logic_vector(g_data_width-1 downto 0);
we_i : in std_logic;
q_o : out std_logic_vector(g_data_width-1 downto 0);
rd_i : in std_logic;
full_o : out std_logic;
almost_full_o : out std_logic;
q_valid_o : out std_logic
);
end generic_shiftreg_fifo;
architecture rtl of generic_shiftreg_fifo is
component gc_shiftreg
generic (
g_size : integer);
port (
clk_i : in std_logic;
en_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic;
a_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0));
end component;
signal pointer : integer range 0 to g_size-1 := 0;
signal srl_addr : std_logic_vector(f_log2_size(g_size)-1 downto 0) := (others => '0');
signal pointer_zero : std_logic;
signal pointer_full : std_logic;
signal pointer_almost_full : std_logic;
signal empty : std_logic := '1';
signal valid_count : std_logic;
signal do_write : std_logic;
begin
-- Valid write, high when valid to write data to the store.
do_write <= '1' when (rd_i = '1' and we_i = '1')
or (we_i = '1' and pointer_full = '0') else '0';
gen_sregs : for i in 0 to g_data_width-1 generate
U_SRLx : gc_shiftreg
generic map (
g_size => g_size)
port map (
clk_i => clk_i,
en_i => do_write,
d_i => d_i(i),
q_o => q_o(i),
a_i => srl_addr);
end generate gen_sregs;
srl_addr <= std_logic_vector(to_unsigned(pointer, srl_addr'length));
p_empty_logic : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
empty <= '1';
elsif empty = '1' and we_i = '1' then
empty <= '0';
elsif pointer_zero = '1' and rd_i = '1' and we_i = '0' then
empty <= '1';
end if;
end if;
end process;
-- W R Action
-- 0 0 pointer <= pointer
-- 0 1 pointer <= pointer - 1 Read, but no write, so less data in counter
-- 1 0 pointer <= pointer + 1 Write, but no read, so more data in fifo
-- 1 1 pointer <= pointer Read and write, so same number of words in fifo
--
valid_count <= '1' when (
(we_i = '1' and rd_i = '0' and pointer_full = '0' and empty = '0')
or
(we_i = '0' and rd_i = '1' and pointer_zero = '0')
) else '0';
p_gen_address : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
pointer <= 0;
elsif valid_count = '1' then
if we_i = '1' then
pointer <= pointer + 1;
else
pointer <= pointer - 1;
end if;
end if;
end if;
end process;
-- Detect when pointer is zero and maximum
pointer_zero <= '1' when pointer = 0 else '0';
pointer_full <= '1' when pointer = g_size - 1 else '0';
pointer_almost_full <= '1' when pointer_full = '1' or pointer = g_size -3 or pointer = g_size - 2 else '0';
-- assign internal signals to outputs
full_o <= pointer_full;
almost_full_o <= pointer_almost_full;
q_valid_o <= not empty;
end rtl;