summaryrefslogtreecommitdiff
path: root/2004/n/fpga/src/fifo/fifoctlr_cc.v
blob: 83683ede692fa53b978fd027aa60699816076ada (plain)
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
/***********************************************************************\
*                                                                       *
*  Module      : fifoctlr_cc.v                   Last Update: 12/13/99  *
*                                                                       *
*  Description : FIFO controller top level.                             *
*                Implements a 511x8 FIFO with common read/write clocks. *
*                                                                       *
*  The following Verilog code implements a 511x8 FIFO in a Spartan-II   *
*  device.  The inputs are a Clock, a Read Enable, a Write Enable,      *
*  Write Data, and a FIFO_gsr signal as an initial reset.  The outputs  *
*  are Read Data, Full, Empty, and the FIFOcount outputs, which         *
*  indicate roughly how full the FIFO is.                               *
*                                                                       *
\***********************************************************************/

`timescale 1ns / 10ps

`define DATA_WIDTH 7:0
`define ADDR_WIDTH 8:0

module fifoctlr_cc (clock_in, read_enable_in, write_enable_in, 
                    write_data_in, fifo_gsr_in, read_data_out, 
                    full_out, empty_out, fifocount_out );

input clock_in, read_enable_in, write_enable_in, fifo_gsr_in;
input  [`DATA_WIDTH] write_data_in;
output [`DATA_WIDTH] read_data_out;
output full_out, empty_out;
output [3:0] fifocount_out;

wire read_enable = read_enable_in;
wire write_enable = write_enable_in;
wire fifo_gsr = fifo_gsr_in;
wire [`DATA_WIDTH] write_data = write_data_in;
wire [`DATA_WIDTH] read_data;
assign read_data_out = read_data;
reg full, empty;
assign full_out = full;
assign empty_out = empty;

reg [`ADDR_WIDTH] read_addr, write_addr, fcounter;

wire read_allow, write_allow;

assign read_allow = (read_enable && ! empty);
assign write_allow = (write_enable && ! full);

wire gnd = 0;
wire pwr = 1;

/**********************************************************************\
*                                                                      *
* A global buffer is instantianted to avoid skew problems.             * 
*                                                                      *
\**********************************************************************/
 
BUFGP gclk1 (.I(clock_in), .O(clock));

/**********************************************************************\
*                                                                      *
* Block RAM instantiation for FIFO.  Module is 512x8, of which one     * 
* address location is sacrificed for the overall speed of the design.  *
*                                                                      *
\**********************************************************************/

RAMB4_S8_S8 bram1 ( .ADDRA(read_addr), .ADDRB(write_addr), .DIB(write_data), 
                    .DIA({gnd, gnd, gnd, gnd, gnd, gnd, gnd, gnd}), 
                    .WEA(gnd), .WEB(write_allow), .CLKA(clock), 
                    .CLKB(clock), .RSTA(gnd), .RSTB(gnd), 
                    .ENA(read_allow), .ENB(pwr), .DOA(read_data) );

/***********************************************************\
*                                                           *
*  Empty flag is set on fifo_gsr (initial), or when on the  *
*  next clock cycle, Write Enable is low, and either the    *
*  FIFOcount is equal to 0, or it is equal to 1 and Read    *
*  Enable is high (about to go Empty).                      *
*                                                           *
\***********************************************************/

always @(posedge clock or posedge fifo_gsr)
   if (fifo_gsr) empty <= 1;
   else empty <= (! write_enable && (fcounter[8:1] == 8'h0) && 
                  ((fcounter[0] == 0) || read_enable));

/***********************************************************\
*                                                           *
*  Full flag is set on fifo_gsr (but it is cleared on the   *
*  first valid clock edge after fifo_gsr is removed), or    *
*  when on the next clock cycle, Read Enable is low, and    *
*  either the FIFOcount is equal to 1FF (hex), or it is     *
*  equal to 1FE and the Write Enable is high (about to go   *
*  Full).                                                   *
*                                                           *
\***********************************************************/

always @(posedge clock or posedge fifo_gsr)
   if (fifo_gsr) full <= 1;
   else full <= (! read_enable && (fcounter[8:1] == 8'hFF) && 
                 ((fcounter[0] == 1) || write_enable));

/************************************************************\
*                                                            *
*  Generation of Read and Write address pointers.  They use  *
*  LFSR counters, which are very fast.  Because of the       *
*  nature of LFSRs, one address is sacrificed.               *
*                                                            *
\************************************************************/

wire read_linearfeedback, write_linearfeedback;

assign read_linearfeedback =  ! (read_addr[8] ^ read_addr[4]); 
assign write_linearfeedback = ! (write_addr[8] ^ write_addr[4]);

always @(posedge clock or posedge fifo_gsr)
   if (fifo_gsr) read_addr <= 'h0;
   else if (read_allow)
      read_addr <= { read_addr[7], read_addr[6], read_addr[5], 
                     read_addr[4], read_addr[3], read_addr[2], 
                     read_addr[1], read_addr[0], read_linearfeedback };

always @(posedge clock or posedge fifo_gsr)
   if (fifo_gsr) write_addr <= 'h0;
   else if (write_allow)
      write_addr <= { write_addr[7], write_addr[6], write_addr[5], 
                      write_addr[4], write_addr[3], write_addr[2], 
                      write_addr[1], write_addr[0], write_linearfeedback };

/************************************************************\
*                                                            *
*  Generation of FIFOcount outputs.  Used to determine how   *
*  full FIFO is, based on a counter that keeps track of how  *
*  many words are in the FIFO.  Also used to generate Full   *
*  and Empty flags.  Only the upper four bits of the counter *
*  are sent outside the module.                              *
*                                                            *
\************************************************************/

always @(posedge clock or posedge fifo_gsr)
   if (fifo_gsr) fcounter <= 'h0;
   else if ((! read_allow && write_allow) || (read_allow && ! write_allow))
      begin
         if (write_allow)      fcounter <= fcounter + 1;
         else                  fcounter <= fcounter - 1;
      end

assign fifocount_out = fcounter[8:5];

endmodule