| InstructionsThis FIFO design is synchronous, which means it uses common clocks 
              for Read and Write. When both the Read and Write clocks originate 
              from the same source, the FIFO operation and arbitration are simplified, 
              and the Empty and Full flags are easily generated. Linear Feedback Shift Registers (LFSRs) are used for both the read 
              (read_addr) and write (write_addr) address counters. Because they 
              are addressing a RAM, a binary counting sequence is not necessary, 
              and the pseudo-random sequence of the LFSRs is acceptable. They 
              use very little logic, and are therefore much faster than a standard 
              binary implementation. The only drawback is that the FIFO size is 
              reduced by one, to 511x8. The fifo_gsr signal resets all counters. 
             The synchronous nature of the Block SelectRAM+ memory simplifies 
              the timing requirements to meeting setup times. To perform a read, 
              Read Enable (read_enable) is driven High prior to a rising clock 
              edge, and the Read Data (read_data) is presented on the outputs 
              during the next clock cycle. To do a Burst Read, simply leave Read 
              Enable High for as many clock cycles as desired. If Empty goes active 
              after reading, then the last word has been read, and the next Read 
              Data would be invalid. To perform a write, the Write Data (write_data) must be present 
              on the inputs, and Write Enable (write_enable) is driven High prior 
              to a rising clock edge. As long as the Full flag is not set, the 
              Write will be executed. To do a Burst Write, the Write Enable is 
              left High, and new Write Data must be available every cycle. The Empty flag is set when the Next Read Address (next_read_addr) 
              is equal to the current Write Address, and only a Read is being 
              performed. This early decoding allows Empty to be set immediately 
              after the last Read. It is cleared after a Write operation (with 
              no simultaneous Read). Similarly, the Full flag is set when the 
              Next Write Address (next_write_addr) is equal to the current Read 
              Address, and only a Write is being performed. It is cleared after 
              a Read operation (with no simultaneous Write). If both a Read and 
              Write are done in the same clock cycle, there is no change to the 
              status flags. During global reset (FIFO_gsr), both these signals 
              are driven High, to prevent any external logic from interfacing 
              with the FIFO during this time.  A FIFO count (fifocount) is added for convenience, to determine 
              when the FIFO is 1/2 full, 3/4 full, etc. It is a binary count of 
              the number of words currently stored in the FIFO. It is incremented 
              on Writes, decremented on Reads, and stays the same if both operations 
              are performed within the same clock cycle. In this application, 
              only the upper four bits are sent to I/O, but that can easily be 
              modified. VHDL  ---------------------------------------------------------------------- The following VHDL 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. --
 --------------------------------------------------------------------
 
 library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;
 
 entity fifoctlr_cc is
 port (clock_in: IN std_logic;
 read_enable_in: IN std_logic;
 write_enable_in: IN std_logic;
 write_data_in: IN std_logic_vector(7 downto 0);
 FIFO_gsr_in: IN std_logic;
 read_data_out: OUT std_logic_vector(7 downto 0);
 full_out: OUT std_logic;
 empty_out: OUT std_logic;
 fifocount_out: OUT std_logic_vector(3 downto 0));
 END fifoctlr_cc;
 
 architecture fifoctlr_cc_hdl of fifoctlr_cc is
 signal clock: std_logic;
 signal read_enable: std_logic;
 signal write_enable: std_logic;
 signal FIFO_gsr: std_logic;
 signal read_data: std_logic_vector(7 downto 0) := "00000000";
 signal write_data: std_logic_vector(7 downto 0);
 signal full: std_logic;
 signal empty: std_logic;
 signal read_addr: std_logic_vector(8 downto 0) := "000000000";
 signal write_addr: std_logic_vector(8 downto 0) := "000000000";
 signal fcounter: std_logic_vector(8 downto 0) := "000000000";
 signal read_allow: std_logic;
 signal write_allow: std_logic;
 signal gnd: std_logic;
 signal gnd_bus: std_logic_vector(7 downto 0);
 signal pwr: std_logic;
 signal read_linearfeedback: std_logic;
 signal write_linearfeedback: std_logic;
 
 component BUFGP
 port (
 I: IN std_logic;
 O: OUT std_logic);
 END component;
 
 component RAMB4_S8_S8
 port (
 ADDRA: IN std_logic_vector(8 downto 0);
 ADDRB: IN std_logic_vector(8 downto 0);
 DIA: IN std_logic_vector(7 downto 0);
 DIB: IN std_logic_vector(7 downto 0);
 WEA: IN std_logic;
 WEB: IN std_logic;
 CLKA: IN std_logic;
 CLKB: IN std_logic;
 RSTA: IN std_logic;
 RSTB: IN std_logic;
 ENA: IN std_logic;
 ENB: IN std_logic;
 DOA: OUT std_logic_vector(7 downto 0);
 DOB: OUT std_logic_vector(7 downto 0));
 END component;
 
 BEGIN
 read_enable <= read_enable_in;
 write_enable <= write_enable_in;
 FIFO_gsr <= FIFO_gsr_in;
 write_data <= write_data_in;
 read_data_out <= read_data;
 full_out <= full;
 empty_out <= empty;
 read_allow <= (read_enable AND NOT empty);
 write_allow <= (write_enable AND NOT full);
 gnd_bus <= "00000000";
 gnd <= '0';
 pwr <= '1';
 
 ---------------------------------------------------------------------
 -- A global buffer is instantianted to avoid skew problems. --
 ---------------------------------------------------------------------
 
 gclk1: BUFGP port map (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.---------------------------------------------------------------------
 
 bram1: RAMB4_S8_S8 port map (ADDRA => read_addr, ADDRB => write_addr,
 DIB => write_data, DIA => gnd_bus, 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). --
 ---------------------------------------------------------------
 
 proc1: PROCESS (clock, FIFO_gsr)
 BEGIN
 IF (FIFO_gsr = '1') THEN
 empty <= '1';
 ELSIF (clock'EVENT AND clock = '1') THEN
 IF ((fcounter(8 downto 1) = "00000000") AND (write_enable = '0') 
              AND
 ((fcounter(0) = '0') OR (read_enable = '1'))) THEN
 empty <= '1';
 ELSE
 empty <= '0';
 END IF;
 END IF;
 END PROCESS proc1;
 
 ---------------------------------------------------------------
 -- 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). --
 ---------------------------------------------------------------
 
 proc2: PROCESS (clock, FIFO_gsr)
 BEGIN
 IF (FIFO_gsr = '1') THEN
 full <= '1';
 ELSIF (clock'EVENT AND clock = '1') THEN
 IF ((fcounter(8 downto 1) = "11111111") AND (read_enable = '0') 
              AND
 ((fcounter(0) = '1') OR (write_enable = '1'))) THEN
 full <= '1';
 ELSE
 full <= '0';
 END IF;
 END IF;
 END PROCESS proc2;
 
 ----------------------------------------------------------------
 -- 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. --
 ----------------------------------------------------------------
 
 read_linearfeedback <= NOT (read_addr(8) XOR read_addr(4));
 write_linearfeedback <= NOT (write_addr(8) XOR write_addr(4));
 
 proc3: PROCESS (clock, FIFO_gsr)
 BEGIN
 IF (FIFO_gsr = '1') THEN
 read_addr <= "000000000";
 ELSIF (clock'EVENT AND clock = '1') THEN
 IF (read_allow = '1') THEN
 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);
 read_addr(0) <= read_linearfeedback;
 END IF;
 END IF;
 END PROCESS proc3;
 
 proc4: PROCESS (clock, FIFO_gsr)
 BEGIN
 IF (FIFO_gsr = '1') THEN
 write_addr <= "000000000";
 ELSIF (clock'EVENT AND clock = '1') THEN
 IF (write_allow = '1') THEN
 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);
 write_addr(0) <= write_linearfeedback;
 END IF;
 END IF;
 END PROCESS proc4;
 
 ----------------------------------------------------------------
 -- 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. --
 ----------------------------------------------------------------
 
 proc5: PROCESS (clock, FIFO_gsr)
 BEGIN
 IF (FIFO_gsr = '1') THEN
 fcounter <= "000000000";
 ELSIF (clock'EVENT AND clock = '1') THEN
 IF (((read_allow = '1') AND (write_allow = '0')) OR
 ((read_allow = '0') AND (write_allow = '1'))) THEN
 IF (write_allow = '1') THEN
 fcounter <= fcounter + '1';
 ELSE
 fcounter <= fcounter - '1';
 END IF;
 END IF;
 END IF;
 END PROCESS proc5;
 
 fifocount_out <= fcounter(8 downto 5);
 
 END fifoctlr_cc_hdl;
 Verilog   
              /******************************************************************\* 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
 
   |