summaryrefslogtreecommitdiff
path: root/2004/n/fpga/src/fifo/fifoctlr_ic.v
diff options
context:
space:
mode:
authorprot2004-02-12 09:00:37 +0000
committerprot2004-02-12 09:00:37 +0000
commitfbc352c9b3161d0f888321e52aeeaf2a682764d6 (patch)
tree6af5ae5e0106cb09aabf7f5b16b4aa3f76dd8a8f /2004/n/fpga/src/fifo/fifoctlr_ic.v
parentaeb2c946ab1952c02d51f89f826d2c1a9ba3d33a (diff)
Ajout des fichiers fifo dans le rep 'src'
Diffstat (limited to '2004/n/fpga/src/fifo/fifoctlr_ic.v')
-rw-r--r--2004/n/fpga/src/fifo/fifoctlr_ic.v349
1 files changed, 349 insertions, 0 deletions
diff --git a/2004/n/fpga/src/fifo/fifoctlr_ic.v b/2004/n/fpga/src/fifo/fifoctlr_ic.v
new file mode 100644
index 0000000..0639334
--- /dev/null
+++ b/2004/n/fpga/src/fifo/fifoctlr_ic.v
@@ -0,0 +1,349 @@
+
+/***********************************************************************\
+* *
+* Module : fifoctlr_ic.v Last Update: 12/13/99 *
+* *
+* Description : FIFO controller top level. *
+* Implements a 511x8 FIFO with independent read/write *
+* clocks. *
+* *
+* The following Verilog code implements a 511x8 FIFO in a Spartan-II *
+* device. The inputs are a Read Clock and Read Enable, a Write Clock *
+* and Write Enable, Write Data, and a FIFO_gsr signal as an initial *
+* reset. The outputs are Read Data, Full, Empty, and the FIFOstatus *
+* outputs, which indicate roughly how full the FIFO is. *
+* *
+\***********************************************************************/
+
+`timescale 1ns / 10ps
+
+`define DATA_WIDTH 7:0
+`define ADDR_WIDTH 8:0
+
+module fifoctlr_ic (read_clock_in, write_clock_in, read_enable_in,
+ write_enable_in, fifo_gsr_in, write_data_in,
+ read_data_out, fifostatus_out, full_out,
+ empty_out);
+
+input read_clock_in, write_clock_in;
+input read_enable_in, write_enable_in;
+input fifo_gsr_in;
+input [`DATA_WIDTH] write_data_in;
+output [`DATA_WIDTH] read_data_out;
+output [4:0] fifostatus_out;
+output full_out, empty_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 [4:0] fifostatus;
+assign fifostatus_out = fifostatus;
+reg full, empty;
+assign full_out = full;
+assign empty_out = empty;
+
+reg [`ADDR_WIDTH] read_addr, write_addr;
+reg [`ADDR_WIDTH] write_addrgray, write_nextgray;
+reg [`ADDR_WIDTH] read_addrgray, read_nextgray, read_lastgray;
+
+wire read_allow, write_allow;
+
+wire [`ADDR_WIDTH] ecomp, aecomp, fcomp, afcomp;
+wire [`ADDR_WIDTH] emuxcyo, aemuxcyo, fmuxcyo, afmuxcyo;
+
+wire emptyg, almostemptyg, fullg, almostfullg;
+wire tempo1, tempo2, tempo3, tempo4;
+wire ecin, fcin, aecin, afcin;
+
+wire gnd = 0;
+wire pwr = 1;
+
+/**********************************************************************\
+* *
+* Global input clock buffers are instantianted for both the read_clock *
+* and the write_clock, to avoid skew problems. *
+* *
+\**********************************************************************/
+
+BUFGP gclkread (.I(read_clock_in), .O(read_clock));
+BUFGP gclkwrite (.I(write_clock_in), .O(write_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(read_clock),
+ .CLKB(write_clock), .RSTA(gnd), .RSTB(gnd),
+ .ENA(read_allow), .ENB(pwr), .DOA(read_data) );
+
+/***********************************************************\
+* *
+* Empty flag is set on fifo_gsr (initial), or when gray *
+* code counters are equal, or when there is one word in *
+* the FIFO, and a Read operation is about to be performed. *
+* *
+\***********************************************************/
+
+always @(posedge read_clock or posedge fifo_gsr)
+ if (fifo_gsr) empty <= 'b1;
+ else empty <= (emptyg || (almostemptyg && read_enable && ! empty));
+
+/***********************************************************\
+* *
+* Full flag is set on fifo_gsr (initial, but it is cleared *
+* on the first valid write_clock edge after fifo_gsr is *
+* de-asserted), or when Gray-code counters are one away *
+* from being equal (the Write Gray-code address is equal *
+* to the Last Read Gray-code address), or when the Next *
+* Write Gray-code address is equal to the Last Read Gray- *
+* code address, and a Write operation is about to be *
+* performed. *
+* *
+\***********************************************************/
+
+always @(posedge write_clock or posedge fifo_gsr)
+ if (fifo_gsr) full <= 'b1;
+ else full <= (fullg || (almostfullg && write_enable && ! full));
+
+/************************************************************\
+* *
+* Generation of Read address pointers. The primary one is *
+* binary (read_addr), and the Gray-code derivatives are *
+* generated via pipelining the binary-to-Gray-code result. *
+* The initial values are important, so they're in sequence. *
+* Grey-code addresses are used so that the registered *
+* Full and Empty flags are always clean, and never in an *
+* unknown state due to the asynchonous relationship of the *
+* Read and Write clocks. In the worst case scenario, Full *
+* and Empty would simply stay active one cycle longer, but *
+* it would not generate an error or give false values. *
+* *
+\************************************************************/
+
+always @(posedge read_clock or posedge fifo_gsr)
+ if (fifo_gsr) read_addr <= 'h0;
+ else if (read_allow) read_addr <= read_addr + 1;
+
+always @(posedge read_clock or posedge fifo_gsr)
+ if (fifo_gsr) read_nextgray <= 9'b100000000;
+ else if (read_allow)
+ read_nextgray <= { read_addr[8], (read_addr[8] ^ read_addr[7]),
+ (read_addr[7] ^ read_addr[6]), (read_addr[6] ^ read_addr[5]),
+ (read_addr[5] ^ read_addr[4]), (read_addr[4] ^ read_addr[3]),
+ (read_addr[3] ^ read_addr[2]), (read_addr[2] ^ read_addr[1]),
+ (read_addr[1] ^ read_addr[0]) };
+
+always @(posedge read_clock or posedge fifo_gsr)
+ if (fifo_gsr) read_addrgray <= 9'b100000001;
+ else if (read_allow) read_addrgray <= read_nextgray;
+
+always @(posedge read_clock or posedge fifo_gsr)
+ if (fifo_gsr) read_lastgray <= 9'b100000011;
+ else if (read_allow) read_lastgray <= read_addrgray;
+
+/************************************************************\
+* *
+* Generation of Write address pointers. Identical copy of *
+* read pointer generation above, except for names. *
+* *
+\************************************************************/
+
+always @(posedge write_clock or posedge fifo_gsr)
+ if (fifo_gsr) write_addr <= 'h0;
+ else if (write_allow) write_addr <= write_addr + 1;
+
+always @(posedge write_clock or posedge fifo_gsr)
+ if (fifo_gsr) write_nextgray <= 9'b100000000;
+ else if (write_allow)
+ write_nextgray <= { write_addr[8], (write_addr[8] ^ write_addr[7]),
+ (write_addr[7] ^ write_addr[6]), (write_addr[6] ^ write_addr[5]),
+ (write_addr[5] ^ write_addr[4]), (write_addr[4] ^ write_addr[3]),
+ (write_addr[3] ^ write_addr[2]), (write_addr[2] ^ write_addr[1]),
+ (write_addr[1] ^ write_addr[0]) };
+
+always @(posedge write_clock or posedge fifo_gsr)
+ if (fifo_gsr) write_addrgray <= 9'b100000001;
+ else if (write_allow) write_addrgray <= write_nextgray;
+
+/************************************************************\
+* *
+* Generation of FIFOstatus outputs. Used to determine how *
+* full FIFO is, based on how far the Write pointer is ahead *
+* of the Read pointer. Additional precision can be gained *
+* by using additional (top) bits of Gray-code addresses. *
+* *
+\************************************************************/
+
+always @(posedge write_clock or posedge fifo_gsr)
+// for 0 to 1/4 full (quads equal)
+ if (fifo_gsr) fifostatus[0] <= 'b1;
+ else fifostatus[0] <= (read_addrgray[8:7] == write_addrgray[8:7]) &&
+ ! (fifostatus[3] || fifostatus[4]);
+
+always @(posedge write_clock or posedge fifo_gsr)
+// for 1 byte to 1/2 full (quad 1 ahead)
+ if (fifo_gsr) fifostatus[1] <= 'b0;
+ else fifostatus[1] <=
+ ((read_addrgray[8:7]=='b00)&&(write_addrgray[8:7]=='b01)) ||
+ ((read_addrgray[8:7]=='b01)&&(write_addrgray[8:7]=='b11)) ||
+ ((read_addrgray[8:7]=='b11)&&(write_addrgray[8:7]=='b10)) ||
+ ((read_addrgray[8:7]=='b10)&&(write_addrgray[8:7]=='b00));
+
+always @(posedge write_clock or posedge fifo_gsr)
+// for 1/4 to 3/4 full (quad 2 ahead)
+ if (fifo_gsr) fifostatus[2] <= 'b0;
+ else fifostatus[2] <=
+ ((read_addrgray[8:7]=='b00)&&(write_addrgray[8:7]=='b11)) ||
+ ((read_addrgray[8:7]=='b01)&&(write_addrgray[8:7]=='b10)) ||
+ ((read_addrgray[8:7]=='b11)&&(write_addrgray[8:7]=='b00)) ||
+ ((read_addrgray[8:7]=='b10)&&(write_addrgray[8:7]=='b01));
+
+always @(posedge write_clock or posedge fifo_gsr)
+// for 1/2 to full (quad 3 ahead)
+ if (fifo_gsr) fifostatus[3] <= 'b0;
+ else fifostatus[3] <=
+ ((read_addrgray[8:7]=='b00)&&(write_addrgray[8:7]=='b10)) ||
+ ((read_addrgray[8:7]=='b01)&&(write_addrgray[8:7]=='b00)) ||
+ ((read_addrgray[8:7]=='b11)&&(write_addrgray[8:7]=='b01)) ||
+ ((read_addrgray[8:7]=='b10)&&(write_addrgray[8:7]=='b11));
+
+always @(posedge write_clock or posedge fifo_gsr)
+// for 3/4 to full (quad 4 ahead/equal)
+ if (fifo_gsr) fifostatus[4] <= 'b0;
+ else fifostatus[4] <= (read_addrgray[8:7] == write_addrgray[8:7]) &&
+ (fifostatus[3] || fifostatus[4]);
+
+/************************************************************\
+* *
+* Allow flags determine whether FIFO control logic can *
+* operate. If read_enable is driven high, and the FIFO is *
+* not Empty, then Reads are allowed. Similarly, if the *
+* write_enable signal is high, and the FIFO is not Full, *
+* then Writes are allowed. *
+* *
+\************************************************************/
+
+assign read_allow = (read_enable && ! empty);
+assign write_allow = (write_enable && ! full);
+
+/************************************************************\
+* *
+* The four conditions decoded with special carry logic are *
+* Empty, AlmostEmpty, Full, and AlmostFull. These are *
+* used to determine the next state of the Full/Empty *
+* flags. Carry logic is used for optimal speed. *
+* *
+* When the Write/Read Gray-code addresses are equal, the *
+* FIFO is Empty, and emptyg (combinatorial) is asserted. *
+* When the Write Gray-code address is equal to the Next *
+* Read Gray-code address (1 word in the FIFO), then the *
+* FIFO potentially could be going Empty (if read_enable is *
+* asserted, which is used in the logic that generates the *
+* registered version of Empty). *
+* *
+* Similarly, when the Write Gray-code address is equal to *
+* the Last Read Gray-code address, the FIFO is full. To *
+* have utilized the full address space (512 addresses) *
+* would have required extra logic to determine Full/Empty *
+* on equal addresses, and this would have slowed down the *
+* overall performance. Lastly, when the Next Write Gray- *
+* code address is equal to the Last Read Gray-code address *
+* the FIFO is Almost Full, with only one word left, and *
+* it is conditional on write_enable being asserted. *
+* *
+\************************************************************/
+
+assign ecomp[0] = (write_addrgray[0] == read_addrgray[0]);
+assign ecomp[1] = (write_addrgray[1] == read_addrgray[1]);
+assign ecomp[2] = (write_addrgray[2] == read_addrgray[2]);
+assign ecomp[3] = (write_addrgray[3] == read_addrgray[3]);
+assign ecomp[4] = (write_addrgray[4] == read_addrgray[4]);
+assign ecomp[5] = (write_addrgray[5] == read_addrgray[5]);
+assign ecomp[6] = (write_addrgray[6] == read_addrgray[6]);
+assign ecomp[7] = (write_addrgray[7] == read_addrgray[7]);
+assign ecomp[8] = (write_addrgray[8] == read_addrgray[8]);
+
+MUXCY_L emuxcyi (.DI(pwr), .CI(pwr), .S(pwr), .LO(ecin));
+MUXCY_L emuxcy0 (.DI(gnd), .CI(ecin), .S(ecomp[0]), .LO(emuxcyo[0]));
+MUXCY_L emuxcy1 (.DI(gnd), .CI(emuxcyo[0]), .S(ecomp[1]), .LO(emuxcyo[1]));
+MUXCY_L emuxcy2 (.DI(gnd), .CI(emuxcyo[1]), .S(ecomp[2]), .LO(emuxcyo[2]));
+MUXCY_L emuxcy3 (.DI(gnd), .CI(emuxcyo[2]), .S(ecomp[3]), .LO(emuxcyo[3]));
+MUXCY_L emuxcy4 (.DI(gnd), .CI(emuxcyo[3]), .S(ecomp[4]), .LO(emuxcyo[4]));
+MUXCY_L emuxcy5 (.DI(gnd), .CI(emuxcyo[4]), .S(ecomp[5]), .LO(emuxcyo[5]));
+MUXCY_L emuxcy6 (.DI(gnd), .CI(emuxcyo[5]), .S(ecomp[6]), .LO(emuxcyo[6]));
+MUXCY_L emuxcy7 (.DI(gnd), .CI(emuxcyo[6]), .S(ecomp[7]), .LO(emuxcyo[7]));
+MUXCY_L emuxcy8 (.DI(gnd), .CI(emuxcyo[7]), .S(ecomp[8]), .LO(emptyg));
+
+assign aecomp[0] = (write_addrgray[0] == read_nextgray[0]);
+assign aecomp[1] = (write_addrgray[1] == read_nextgray[1]);
+assign aecomp[2] = (write_addrgray[2] == read_nextgray[2]);
+assign aecomp[3] = (write_addrgray[3] == read_nextgray[3]);
+assign aecomp[4] = (write_addrgray[4] == read_nextgray[4]);
+assign aecomp[5] = (write_addrgray[5] == read_nextgray[5]);
+assign aecomp[6] = (write_addrgray[6] == read_nextgray[6]);
+assign aecomp[7] = (write_addrgray[7] == read_nextgray[7]);
+assign aecomp[8] = (write_addrgray[8] == read_nextgray[8]);
+
+MUXCY_L aemuxcyi (.DI(pwr), .CI(pwr), .S(pwr), .LO(aecin));
+MUXCY_L aemuxcy0 (.DI(gnd), .CI(aecin), .S(aecomp[0]), .LO(aemuxcyo[0]));
+MUXCY_L aemuxcy1 (.DI(gnd), .CI(aemuxcyo[0]), .S(aecomp[1]), .LO(aemuxcyo[1]));
+MUXCY_L aemuxcy2 (.DI(gnd), .CI(aemuxcyo[1]), .S(aecomp[2]), .LO(aemuxcyo[2]));
+MUXCY_L aemuxcy3 (.DI(gnd), .CI(aemuxcyo[2]), .S(aecomp[3]), .LO(aemuxcyo[3]));
+MUXCY_L aemuxcy4 (.DI(gnd), .CI(aemuxcyo[3]), .S(aecomp[4]), .LO(aemuxcyo[4]));
+MUXCY_L aemuxcy5 (.DI(gnd), .CI(aemuxcyo[4]), .S(aecomp[5]), .LO(aemuxcyo[5]));
+MUXCY_L aemuxcy6 (.DI(gnd), .CI(aemuxcyo[5]), .S(aecomp[6]), .LO(aemuxcyo[6]));
+MUXCY_L aemuxcy7 (.DI(gnd), .CI(aemuxcyo[6]), .S(aecomp[7]), .LO(aemuxcyo[7]));
+MUXCY_L aemuxcy8 (.DI(gnd), .CI(aemuxcyo[7]), .S(aecomp[8]), .LO(almostemptyg));
+
+assign fcomp[0] = (write_addrgray[0] == read_lastgray[0]);
+assign fcomp[1] = (write_addrgray[1] == read_lastgray[1]);
+assign fcomp[2] = (write_addrgray[2] == read_lastgray[2]);
+assign fcomp[3] = (write_addrgray[3] == read_lastgray[3]);
+assign fcomp[4] = (write_addrgray[4] == read_lastgray[4]);
+assign fcomp[5] = (write_addrgray[5] == read_lastgray[5]);
+assign fcomp[6] = (write_addrgray[6] == read_lastgray[6]);
+assign fcomp[7] = (write_addrgray[7] == read_lastgray[7]);
+assign fcomp[8] = (write_addrgray[8] == read_lastgray[8]);
+
+MUXCY_L fmuxcyi (.DI(pwr), .CI(pwr), .S(pwr), .LO(fcin));
+MUXCY_L fmuxcy0 (.DI(gnd), .CI(fcin), .S(fcomp[0]), .LO(fmuxcyo[0]));
+MUXCY_L fmuxcy1 (.DI(gnd), .CI(fmuxcyo[0]), .S(fcomp[1]), .LO(fmuxcyo[1]));
+MUXCY_L fmuxcy2 (.DI(gnd), .CI(fmuxcyo[1]), .S(fcomp[2]), .LO(fmuxcyo[2]));
+MUXCY_L fmuxcy3 (.DI(gnd), .CI(fmuxcyo[2]), .S(fcomp[3]), .LO(fmuxcyo[3]));
+MUXCY_L fmuxcy4 (.DI(gnd), .CI(fmuxcyo[3]), .S(fcomp[4]), .LO(fmuxcyo[4]));
+MUXCY_L fmuxcy5 (.DI(gnd), .CI(fmuxcyo[4]), .S(fcomp[5]), .LO(fmuxcyo[5]));
+MUXCY_L fmuxcy6 (.DI(gnd), .CI(fmuxcyo[5]), .S(fcomp[6]), .LO(fmuxcyo[6]));
+MUXCY_L fmuxcy7 (.DI(gnd), .CI(fmuxcyo[6]), .S(fcomp[7]), .LO(fmuxcyo[7]));
+MUXCY_L fmuxcy8 (.DI(gnd), .CI(fmuxcyo[7]), .S(fcomp[8]), .LO(fullg));
+
+assign afcomp[0] = (write_nextgray[0] == read_lastgray[0]);
+assign afcomp[1] = (write_nextgray[1] == read_lastgray[1]);
+assign afcomp[2] = (write_nextgray[2] == read_lastgray[2]);
+assign afcomp[3] = (write_nextgray[3] == read_lastgray[3]);
+assign afcomp[4] = (write_nextgray[4] == read_lastgray[4]);
+assign afcomp[5] = (write_nextgray[5] == read_lastgray[5]);
+assign afcomp[6] = (write_nextgray[6] == read_lastgray[6]);
+assign afcomp[7] = (write_nextgray[7] == read_lastgray[7]);
+assign afcomp[8] = (write_nextgray[8] == read_lastgray[8]);
+
+MUXCY_L afmuxcyi (.DI(pwr), .CI(pwr), .S(pwr), .LO(afcin));
+MUXCY_L afmuxcy0 (.DI(gnd), .CI(afcin), .S(afcomp[0]), .LO(afmuxcyo[0]));
+MUXCY_L afmuxcy1 (.DI(gnd), .CI(afmuxcyo[0]), .S(afcomp[1]), .LO(afmuxcyo[1]));
+MUXCY_L afmuxcy2 (.DI(gnd), .CI(afmuxcyo[1]), .S(afcomp[2]), .LO(afmuxcyo[2]));
+MUXCY_L afmuxcy3 (.DI(gnd), .CI(afmuxcyo[2]), .S(afcomp[3]), .LO(afmuxcyo[3]));
+MUXCY_L afmuxcy4 (.DI(gnd), .CI(afmuxcyo[3]), .S(afcomp[4]), .LO(afmuxcyo[4]));
+MUXCY_L afmuxcy5 (.DI(gnd), .CI(afmuxcyo[4]), .S(afcomp[5]), .LO(afmuxcyo[5]));
+MUXCY_L afmuxcy6 (.DI(gnd), .CI(afmuxcyo[5]), .S(afcomp[6]), .LO(afmuxcyo[6]));
+MUXCY_L afmuxcy7 (.DI(gnd), .CI(afmuxcyo[6]), .S(afcomp[7]), .LO(afmuxcyo[7]));
+MUXCY_L afmuxcy8 (.DI(gnd), .CI(afmuxcyo[7]), .S(afcomp[8]), .LO(almostfullg));
+
+endmodule
+