//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// adbg_bytefifo.v ////
|
//// adbg_bytefifo.v ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// A simple byte-wide FIFO with byte and free space counts ////
|
//// A simple byte-wide FIFO with byte and free space counts ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// Nathan Yawn (nathan.yawn@opencores.org) ////
|
//// Nathan Yawn (nathan.yawn@opencores.org) ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2010 Authors ////
|
//// Copyright (C) 2010 Authors ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
// This is an 8-entry, byte-wide, single-port FIFO. It can either
|
// This is an 8-entry, byte-wide, single-port FIFO. It can either
|
// push or pop a byte each clock cycle (but not both). It includes
|
// push or pop a byte each clock cycle (but not both). It includes
|
// outputs indicating the number of bytes in the FIFO, and the number
|
// outputs indicating the number of bytes in the FIFO, and the number
|
// of bytes free - if you don't connect BYTES_FREE, the synthesis
|
// of bytes free - if you don't connect BYTES_FREE, the synthesis
|
// tool should eliminate the hardware to generate it.
|
// tool should eliminate the hardware to generate it.
|
//
|
//
|
// This attempts to use few resources. There is only 1 counter,
|
// This attempts to use few resources. There is only 1 counter,
|
// and only 1 decoder. The FIFO works like a big shift register:
|
// and only 1 decoder. The FIFO works like a big shift register:
|
// bytes are always written to entry '0' of the FIFO, and older
|
// bytes are always written to entry '0' of the FIFO, and older
|
// bytes are shifted toward entry '7' as newer bytes are added.
|
// bytes are shifted toward entry '7' as newer bytes are added.
|
// The counter determines which entry the output reads.
|
// The counter determines which entry the output reads.
|
//
|
//
|
// One caveat is that the DATA_OUT will glitch during a 'push'
|
// One caveat is that the DATA_OUT will glitch during a 'push'
|
// operation. If the output is being sent to another clock
|
// operation. If the output is being sent to another clock
|
// domain, you should register it first.
|
// domain, you should register it first.
|
//
|
//
|
// Ports:
|
// Ports:
|
// CLK: Clock for all synchronous elements
|
// CLK: Clock for all synchronous elements
|
// RST: Zeros the counter and all registers asynchronously
|
// RST: Zeros the counter and all registers asynchronously
|
// DATA_IN: Data to be pushed into the FIFO
|
// DATA_IN: Data to be pushed into the FIFO
|
// DATA_OUT: Always shows the data at the head of the FIFO, 'XX' if empty
|
// DATA_OUT: Always shows the data at the head of the FIFO, '00' if empty
|
// PUSH_POPn: When high (and EN is high), DATA_IN will be pushed onto the
|
// PUSH_POPn: When high (and EN is high), DATA_IN will be pushed onto the
|
// FIFO and the count will be incremented at the next posedge
|
// FIFO and the count will be incremented at the next posedge
|
// of CLK (assuming the FIFO is not full). When low (and EN
|
// of CLK (assuming the FIFO is not full). When low (and EN
|
// is high), the count will be decremented and the output changed
|
// is high), the count will be decremented and the output changed
|
// to the next value in the FIFO (assuming FIFO not empty).
|
// to the next value in the FIFO (assuming FIFO not empty).
|
// EN: When high at posedege CLK, a push or pop operation will be performed,
|
// EN: When high at posedege CLK, a push or pop operation will be performed,
|
// based on the value of PUSH_POPn, assuming sufficient data or space.
|
// based on the value of PUSH_POPn, assuming sufficient data or space.
|
// BYTES_AVAIL: Number of bytes in the FIFO. May be in the range 0 to 8.
|
// BYTES_AVAIL: Number of bytes in the FIFO. May be in the range 0 to 8.
|
// BYTES_FREE: Free space in the FIFO. May be in the range 0 to 8.
|
// BYTES_FREE: Free space in the FIFO. May be in the range 0 to 8.
|
|
|
|
|
// Top module
|
// Top module
|
module `VARIANT`BYTEFIFO (
|
module `VARIANT`BYTEFIFO (
|
CLK,
|
CLK,
|
RST,
|
RST,
|
DATA_IN,
|
DATA_IN,
|
DATA_OUT,
|
DATA_OUT,
|
PUSH_POPn,
|
PUSH_POPn,
|
EN,
|
EN,
|
BYTES_AVAIL,
|
BYTES_AVAIL,
|
BYTES_FREE
|
BYTES_FREE
|
);
|
);
|
|
|
|
|
input CLK;
|
input CLK;
|
input RST;
|
input RST;
|
input [7:0] DATA_IN;
|
input [7:0] DATA_IN;
|
output [7:0] DATA_OUT;
|
output [7:0] DATA_OUT;
|
input PUSH_POPn;
|
input PUSH_POPn;
|
input EN;
|
input EN;
|
output [3:0] BYTES_AVAIL;
|
output [3:0] BYTES_AVAIL;
|
output [3:0] BYTES_FREE;
|
output [3:0] BYTES_FREE;
|
|
|
reg [7:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
|
reg [7:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
|
reg [3:0] counter;
|
reg [3:0] counter;
|
|
|
reg [7:0] DATA_OUT;
|
reg [7:0] DATA_OUT;
|
wire [3:0] BYTES_AVAIL;
|
wire [3:0] BYTES_AVAIL;
|
wire [3:0] BYTES_FREE;
|
wire [3:0] BYTES_FREE;
|
wire push_ok;
|
wire push_ok;
|
wire pop_ok;
|
wire pop_ok;
|
|
|
///////////////////////////////////
|
///////////////////////////////////
|
// Combinatorial assignments
|
// Combinatorial assignments
|
|
|
assign BYTES_AVAIL = counter;
|
assign BYTES_AVAIL = counter;
|
assign BYTES_FREE = 4'h8 - BYTES_AVAIL;
|
assign BYTES_FREE = 4'h8 - BYTES_AVAIL;
|
assign push_ok = !(counter == 4'h8);
|
assign push_ok = !(counter == 4'h8);
|
assign pop_ok = !(counter == 4'h0);
|
assign pop_ok = !(counter == 4'h0);
|
|
|
///////////////////////////////////
|
///////////////////////////////////
|
// FIFO memory / shift registers
|
// FIFO memory / shift registers
|
|
|
// Reg 0 - takes input from DATA_IN
|
// Reg 0 - takes input from DATA_IN
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg0 <= 8'h0;
|
reg0 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg0 <= DATA_IN;
|
reg0 <= DATA_IN;
|
end
|
end
|
|
|
|
|
// Reg 1 - takes input from reg0
|
// Reg 1 - takes input from reg0
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg1 <= 8'h0;
|
reg1 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg1 <= reg0;
|
reg1 <= reg0;
|
end
|
end
|
|
|
|
|
// Reg 2 - takes input from reg1
|
// Reg 2 - takes input from reg1
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg2 <= 8'h0;
|
reg2 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg2 <= reg1;
|
reg2 <= reg1;
|
end
|
end
|
|
|
|
|
// Reg 3 - takes input from reg2
|
// Reg 3 - takes input from reg2
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg3 <= 8'h0;
|
reg3 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg3 <= reg2;
|
reg3 <= reg2;
|
end
|
end
|
|
|
|
|
// Reg 4 - takes input from reg3
|
// Reg 4 - takes input from reg3
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg4 <= 8'h0;
|
reg4 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg4 <= reg3;
|
reg4 <= reg3;
|
end
|
end
|
|
|
|
|
// Reg 5 - takes input from reg4
|
// Reg 5 - takes input from reg4
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg5 <= 8'h0;
|
reg5 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg5 <= reg4;
|
reg5 <= reg4;
|
end
|
end
|
|
|
|
|
// Reg 6 - takes input from reg5
|
// Reg 6 - takes input from reg5
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg6 <= 8'h0;
|
reg6 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg6 <= reg5;
|
reg6 <= reg5;
|
end
|
end
|
|
|
|
|
// Reg 7 - takes input from reg6
|
// Reg 7 - takes input from reg6
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST)
|
if(RST)
|
reg7 <= 8'h0;
|
reg7 <= 8'h0;
|
else if(EN & PUSH_POPn & push_ok)
|
else if(EN & PUSH_POPn & push_ok)
|
reg7 <= reg6;
|
reg7 <= reg6;
|
end
|
end
|
|
|
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
// Read counter
|
// Read counter
|
// This is a 4-bit saturating up/down counter
|
// This is a 4-bit saturating up/down counter
|
// The 'saturating' is done via push_ok and pop_ok
|
// The 'saturating' is done via push_ok and pop_ok
|
|
|
always @ (posedge CLK or posedge RST)
|
always @ (posedge CLK or posedge RST)
|
begin
|
begin
|
if(RST) counter <= 4'h0;
|
if(RST) counter <= 4'h0;
|
else if(EN & PUSH_POPn & push_ok) counter <= counter + 4'h1;
|
else if(EN & PUSH_POPn & push_ok) counter <= counter + 4'h1;
|
else if(EN & (~PUSH_POPn) & pop_ok) counter <= counter - 4'h1;
|
else if(EN & (~PUSH_POPn) & pop_ok) counter <= counter - 4'h1;
|
end
|
end
|
|
|
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
// Output decoder
|
// Output decoder
|
|
|
always @ (counter or reg0 or reg1 or reg2 or reg3 or reg4 or reg5
|
always @ (counter or reg0 or reg1 or reg2 or reg3 or reg4 or reg5
|
or reg6 or reg7)
|
or reg6 or reg7)
|
begin
|
begin
|
case (counter)
|
case (counter)
|
4'h1: DATA_OUT = reg0;
|
4'h1: DATA_OUT = reg0;
|
4'h2: DATA_OUT = reg1;
|
4'h2: DATA_OUT = reg1;
|
4'h3: DATA_OUT = reg2;
|
4'h3: DATA_OUT = reg2;
|
4'h4: DATA_OUT = reg3;
|
4'h4: DATA_OUT = reg3;
|
4'h5: DATA_OUT = reg4;
|
4'h5: DATA_OUT = reg4;
|
4'h6: DATA_OUT = reg5;
|
4'h6: DATA_OUT = reg5;
|
4'h7: DATA_OUT = reg6;
|
4'h7: DATA_OUT = reg6;
|
4'h8: DATA_OUT = reg7;
|
4'h8: DATA_OUT = reg7;
|
default: DATA_OUT = 8'hXX;
|
default: DATA_OUT = 8'h00;
|
endcase
|
endcase
|
end
|
end
|
|
|
|
|
endmodule
|
endmodule
|
|
|