OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.storage/] [fifos/] [fifo_mk2/] [1.0/] [vhd/] [fifo_2clk.vhd] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
-------------------------------------------------------------------------------
2
-- Title      : Basic asynchronous FIFO with two clocks
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : fifo_2clk.vhd
6
-- Author     : Lasse Lehtonen
7
-- Company    : 
8
-- Created    : 2011-01-13
9
-- Last update: 2011-11-29
10
-- Platform   : 
11
-- Standard   : VHDL'93
12
-------------------------------------------------------------------------------
13
-- Description:
14
--
15
--   Fully asynchronous fifo.
16
--
17
--   Idea from:
18
--     Cummings et al., Simulation and Synthesis Techniques for Asynchronous
19
--     FIFO Design with Asynchronous Pointer Comparisons, SNUG San Jose 2002
20
--
21
--
22
-------------------------------------------------------------------------------
23
-- Copyright (c) 2011 
24
-------------------------------------------------------------------------------
25
-- Revisions  :
26
-- Date        Version  Author  Description
27
-- 2011-01-13  1.0      ase     Created
28
-------------------------------------------------------------------------------
29
 
30
library ieee;
31
use ieee.std_logic_1164.all;
32
use ieee.numeric_std.all;
33
 
34
 
35
entity fifo_2clk is
36
 
37
  generic (
38
    data_width_g : positive;
39
    depth_g      : positive);
40
 
41
  port (
42
    rst_n     : in  std_logic;
43
    -- Write
44
    clk_wr    : in  std_logic;
45
    we_in     : in  std_logic;
46
    data_in   : in  std_logic_vector(data_width_g-1 downto 0);
47
    full_out  : out std_logic;
48
    -- Read
49
    clk_rd    : in  std_logic;
50
    re_in     : in  std_logic;
51
    data_out  : out std_logic_vector(data_width_g-1 downto 0);
52
    empty_out : out std_logic);
53
 
54
end entity fifo_2clk;
55
 
56
 
57
architecture rtl of fifo_2clk is
58
 
59
  -----------------------------------------------------------------------------
60
  -- FUNCTIONS
61
  -----------------------------------------------------------------------------
62
  -- purpose: Return ceiling log 2 of n
63
  function log2_ceil (
64
    constant n : positive)
65
    return positive is
66
    variable retval : positive := 1;
67
  begin  -- function log2_ceil
68
    while 2**retval < n loop
69
      retval := retval + 1;
70
    end loop;
71
    return retval;
72
  end function log2_ceil;
73
 
74
  -- binary to graycode conversion
75
  function bin2gray (
76
    signal num : integer range 0 to depth_g-1)
77
    return std_logic_vector is
78
    variable retval : std_logic_vector(log2_ceil(depth_g)-1 downto 0);
79
    variable d1     : std_logic_vector(log2_ceil(depth_g)-1 downto 0);
80
  begin
81
    d1     := std_logic_vector((to_unsigned(num, log2_ceil(depth_g))));
82
    retval := d1 xor ('0' & d1(log2_ceil(depth_g)-1 downto 1));
83
    return retval;
84
  end function bin2gray;
85
 
86
  -----------------------------------------------------------------------------
87
  -- CONSTANTS
88
  -----------------------------------------------------------------------------
89
  constant addr_width_c : positive := log2_ceil(depth_g);
90
 
91
  -----------------------------------------------------------------------------
92
  -- REGISTERS
93
  -----------------------------------------------------------------------------
94
  signal wr_addr_r : integer range 0 to depth_g-1;
95
  signal rd_addr_r : integer range 0 to depth_g-1;
96
  signal full_1_r  : std_logic;
97
  signal full_2_r  : std_logic;
98
  signal empty_1_r : std_logic;
99
  signal empty_2_r : std_logic;
100
 
101
  -----------------------------------------------------------------------------
102
  -- COMBINATORIAL SIGNALS
103
  -----------------------------------------------------------------------------
104
  signal next_wr_addr : integer range 0 to depth_g-1;
105
  signal next_rd_addr : integer range 0 to depth_g-1;
106
  signal wr_addr      : std_logic_vector(addr_width_c-1 downto 0);
107
  signal rd_addr      : std_logic_vector(addr_width_c-1 downto 0);
108
  signal we           : std_logic;
109
  signal dirset_n     : std_logic;
110
  signal dirclr_n     : std_logic;
111
  signal direction    : std_logic;
112
  signal empty_n      : std_logic;
113
  signal full_n       : std_logic;
114
 
115
begin  -- architecture rtl
116
 
117
 
118
  full_out  <= full_2_r;
119
  empty_out <= empty_2_r;
120
 
121
  -----------------------------------------------------------------------------
122
  -- WRITE
123
  -----------------------------------------------------------------------------
124
 
125
  write_p : process (clk_wr, rst_n)
126
  begin  -- process write_p
127
    if rst_n = '0' then                 -- asynchronous reset (active low)
128
 
129
      wr_addr_r <= 0;
130
 
131
    elsif clk_wr'event and clk_wr = '1' then  -- rising clock edge
132
 
133
      if we_in = '1' and full_2_r = '0' then
134
        wr_addr_r <= next_wr_addr;
135
      end if;
136
 
137
    end if;
138
  end process write_p;
139
 
140
  we <= we_in and not full_2_r;
141
 
142
  -----------------------------------------------------------------------------
143
  -- READ
144
  -----------------------------------------------------------------------------
145
 
146
  read_p : process (clk_rd, rst_n)
147
  begin  -- process read_p
148
    if rst_n = '0' then                 -- asynchronous reset (active low)
149
 
150
      rd_addr_r <= 0;
151
 
152
    elsif clk_rd'event and clk_rd = '1' then  -- rising clock edge
153
 
154
      if re_in = '1' and empty_2_r = '0' then
155
        rd_addr_r <= next_rd_addr;
156
      end if;
157
 
158
    end if;
159
  end process read_p;
160
 
161
  -----------------------------------------------------------------------------
162
  -- RAM
163
  -----------------------------------------------------------------------------
164
 
165
  wr_addr <= std_logic_vector(to_unsigned(wr_addr_r, addr_width_c));
166
  rd_addr <= std_logic_vector(to_unsigned(rd_addr_r, addr_width_c));
167
 
168
  ram_2clk_1 : entity work.ram_1clk
169
    generic map (
170
      data_width_g => data_width_g,
171
      addr_width_g => addr_width_c,
172
      depth_g      => depth_g,
173
      out_reg_en_g => 0)
174
    port map (
175
      clk        => clk_wr,
176
      wr_addr_in => wr_addr,
177
      rd_addr_in => rd_addr,
178
      we_in      => we,
179
      data_in    => data_in,
180
      data_out   => data_out);
181
 
182
  -----------------------------------------------------------------------------
183
  -- NEXT ADDRESSES
184
  -----------------------------------------------------------------------------
185
 
186
  next_wr_addr_p : process (wr_addr_r) is
187
  begin
188
 
189
    if wr_addr_r = depth_g-1 then
190
      next_wr_addr <= 0;
191
    else
192
      next_wr_addr <= wr_addr_r + 1;
193
    end if;
194
 
195
  end process next_wr_addr_p;
196
 
197
  next_rd_addr_p : process (rd_addr_r) is
198
  begin
199
 
200
    if rd_addr_r = depth_g-1 then
201
      next_rd_addr <= 0;
202
    else
203
      next_rd_addr <= rd_addr_r + 1;
204
    end if;
205
 
206
  end process next_rd_addr_p;
207
 
208
  -----------------------------------------------------------------------------
209
  -- ASYNC COMPARISON (FULL AND EMPTY GENERATION)
210
  -----------------------------------------------------------------------------
211
 
212
  dirgen_p : process (wr_addr_r, rd_addr_r, rst_n)
213
    variable wr_h1 : std_logic;
214
    variable wr_h2 : std_logic;
215
    variable rd_h1 : std_logic;
216
    variable rd_h2 : std_logic;
217
  begin  -- process asyncomp_p
218
 
219
    wr_h1 := bin2gray(wr_addr_r)(addr_width_c-1);
220
    wr_h2 := bin2gray(wr_addr_r)(addr_width_c-2);
221
    rd_h1 := bin2gray(rd_addr_r)(addr_width_c-1);
222
    rd_h2 := bin2gray(rd_addr_r)(addr_width_c-2);
223
 
224
    dirset_n <= not ((wr_h1 xor rd_h2) and not (wr_h2 xor rd_h1));
225
    dirclr_n <= not ((not (wr_h1 xor rd_h2) and (wr_h2 xor rd_h1))
226
                     or not rst_n);
227
 
228
  end process dirgen_p;
229
 
230
  rs_flop_p : process (dirclr_n, dirset_n, direction)
231
  begin  -- process rs_flop_p
232
    if dirclr_n = '0' then
233
      direction <= '0';
234
    elsif dirset_n = '0' then
235
      direction <= '1';
236
    else
237
      direction <= direction;
238
    end if;
239
  end process rs_flop_p;
240
 
241
  full_empty_s : process (direction, wr_addr_r, rd_addr_r)
242
    variable match_v : std_logic;
243
  begin  -- process empty_s
244
    if rd_addr_r = wr_addr_r then
245
      match_v := '1';
246
    else
247
      match_v := '0';
248
    end if;
249
    if match_v = '1' and direction = '1' then
250
      full_n <= '0';
251
    else
252
      full_n <= '1';
253
    end if;
254
    if match_v = '1' and direction = '0' then
255
      empty_n <= '0';
256
    else
257
      empty_n <= '1';
258
    end if;
259
  end process full_empty_s;
260
 
261
  -----------------------------------------------------------------------------
262
  -- Two rs-registers to synchronize empty signal
263
  -----------------------------------------------------------------------------
264
 
265
  empty_sync_1p : process (clk_rd, rst_n, empty_n)
266
  begin  -- process empty_sync_p
267
    if rst_n = '0' then                 -- asynchronous reset (active low)
268
      empty_1_r <= '1';
269
    elsif empty_n = '0' then
270
      empty_1_r <= not empty_n;
271
    elsif clk_rd'event and clk_rd = '1' then  -- rising clock edge
272
      empty_1_r <= not empty_n;
273
    end if;
274
  end process empty_sync_1p;
275
 
276
  empty_sync_2p : process (clk_rd, rst_n, empty_n, empty_1_r)
277
  begin  -- process empty_sync_p
278
    if rst_n = '0' then                 -- asynchronous reset (active low)
279
      empty_2_r <= '1';
280
    elsif empty_n = '0' then
281
      empty_2_r <= empty_1_r;
282
    elsif clk_rd'event and clk_rd = '1' then  -- rising clock edge
283
      empty_2_r <= empty_1_r;
284
    end if;
285
  end process empty_sync_2p;
286
 
287
 ------------------------------------------------------------------------------
288
 -- Two rs-registers to synchronize full signal
289
 ------------------------------------------------------------------------------
290
 
291
  full_sync_1p : process (clk_wr, rst_n, full_n)
292
  begin  -- process empty_sync_p
293
    if rst_n = '0' then                 -- asynchronous reset (active low)
294
      full_1_r <= '0';
295
    elsif full_n = '0' then
296
      full_1_r <= not full_n;
297
    elsif clk_wr'event and clk_wr = '1' then  -- rising clock edge
298
      full_1_r <= not full_n;
299
    end if;
300
  end process full_sync_1p;
301
 
302
  full_sync_2p : process (clk_wr, rst_n, full_n, full_1_r)
303
  begin  -- process empty_sync_p
304
    if rst_n = '0' then                 -- asynchronous reset (active low)
305
      full_2_r <= '0';
306
    elsif full_n = '0' then
307
      full_2_r <= full_1_r;
308
    elsif clk_wr'event and clk_wr = '1' then  -- rising clock edge
309
      full_2_r <= full_1_r;
310
    end if;
311
  end process full_sync_2p;
312
 
313
end architecture rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.