FIFO
利用verilog 完成在FPGA中的FIFO的建構
在網上找來一幅fifo示意圖:

ph為寫位址,pe為讀位址。
在這裡 一直糾結一個問題,就是讀位址和寫位址在完成讀寫後要不要自動加一,以指向下一個位置,一開始就是這樣思路的,但是發現在滿空判斷時出現問題。假設,讀寫都是指向下一個位置,停止寫資料的判斷條件是,讀寫位址相同;停止讀資料也是讀寫位址相同,顯然是不可以的,這樣一旦陷入這樣的條件,則既不能讀也不能寫。最後的妥協方法是寫是指向下一個要寫的位址,讀是指向目前已經讀到位址。
verilog 代碼為
module fifo_length_16(
clock,
reset_n,
read,
write,
fifo_in,
fifo_empty,
fifo_full,
fifo_out
);
input clock;
input reset_n;
input read;
input write;
input [15:0] fifo_in;
output fifo_empty;
output fifo_full;
output[15:0] fifo_out;
parameter MAX_ADDR = 16;
parameter MSB_ADDR = 4;
reg [15:0] mem [MAX_ADDR-1:0];
reg fifo_empty;
reg fifo_full;
reg [15:0] fifo_out;
reg [MSB_ADDR-1 : 0] pe;
reg [MSB_ADDR-1 : 0] ph;
always@(posedge clock or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
pe <= MAX_ADDR-1;
end
else if(read == 1'b1 && pe+1 != ph)
begin
pe = pe + 1'b1;
fifo_out = mem[pe];
end
else
pe <= pe;
end
always@(posedge clock)
begin
if(reset_n == 1'b0)
begin
ph <= 'd0;
end
else if(write == 1'b1 && pe != ph)
begin
ph <= ph + 1'b1;
mem[ph] <= fifo_in;
end
else
ph <= ph;
end
always@(posedge clock or negedge reset_n)
begin
if(reset_n == 1'b0)
begin
fifo_empty <= 1'b0;
fifo_full <= 1'b0;
end
else if ((ph == pe +1)||(ph == pe +2))
begin
fifo_empty <= 1'b1;
end
else if ((pe == ph + 1)||(pe == ph))
begin
fifo_full <= 1'b1;
end
else
begin
fifo_empty <= 1'b0;
fifo_full <= 1'b0;
end
end
endmodule
在寫test時,思路是先往fifo裡寫滿,并且繼續寫操作,然後再全部讀空,來檢測資料出來的順序以及full和empty信号
testbanch代碼:
`timescale 1 ns/ 1 ps
module fifo_length_256_vlg_tst();
// constants
// general purpose registers
// test vector input registers
reg clock;
reg [15:0] fifo_in;
reg read;
reg reset_n;
reg write;
reg [7:0] cnt;
// wires
wire fifo_empty;
wire fifo_full;
wire [15:0] fifo_out;
// assign statements (if any)
fifo_length_256 i1 (
// port map - connection between master ports and signals/registers
.clock(clock),
.fifo_empty(fifo_empty),
.fifo_full(fifo_full),
.fifo_in(fifo_in),
.fifo_out(fifo_out),
.read(read),
.reset_n(reset_n),
.write(write)
);
initial
begin
cnt=0;
clock =0;
fifo_in=0;
read=0;
reset_n=1;
write=0;
# 3 reset_n =0;
# 3 reset_n =1;
#10000 $stop;
end
always
begin
#1 clock =~ clock;
end
always@(posedge clock)
begin
if(reset_n == 1'b0 )
cnt<=1'b0;
else
cnt <= cnt+1'b1;
end
always@(posedge clock)
begin
if(cnt >= 8'd1 && cnt <= 8'd20)
begin
write<= 1'b1;
fifo_in<=fifo_in+1'b1;
end
else if(cnt == 8'd22)
write <= 1'b0;
else if(cnt >= 8'd25 && cnt<= 8'd45)
begin
read <= 1'b1;
end
else if(cnt == 8'd50)
read <= 1'b0;
end
endmodule
modelsim 仿真圖
寫資料
讀資料
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面利用 C/C++來實作。
這裡利用連結清單來完成,有兩個指針,頭指針和尾指針,push就是在頭指針加傳入連結表,pop就是在尾指針删除連結清單,在寫連結清單時。我采用雙連結清單,以及在連結清單描述中添加連結清單長度變量,為後期擴充使用。
代碼:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct _node
{
int data;
struct _node *next;
struct _node *front;
}Node;
typedef struct _linklist
{
Node *head;
Node *tail;
int length;
}Linklist;
typedef Linklist Queue;
Queue* initial_queue(void)
{
Node* n = (Node *)malloc(sizeof(Node));
Queue* q = (Queue *)malloc(sizeof(Queue));
n->next = NULL;
n->front = NULL;
q->head = n;
q->tail = n;
q->length= 0;
return q;
}
void add_queue(Queue * q,int data)
{
Node* n=q->head;
Node* add_n;
if(q->length == 0)
{
//cout<<"length ==0"<<endl;
n->data = data;
q->length += 1;
}
else
{ //cout<<"length !=0"<<endl;
add_n = (Node*)malloc(sizeof(Node));
add_n->data = data;
add_n->next = n;
add_n->front = NULL;
n->front = add_n;
q->head = add_n;
q->length += 1;
}
}
int pop_queue(Queue *q)
{
int data;
Node* n = q->tail;
if(q->length == 1)
{
data=n->data;
q->length -= 1;
}
else if(q->length == 0)
{
cout<<"soory empty "<<endl;
}
else
{
data=n->data;
q->length -= 1;
q->tail = n->front;
q->tail->next = NULL;
free(n);
}
return data;
}
int main()
{
int data;
Queue *q;
Node *n;
q = initial_queue();
add_queue(q,1);
add_queue(q,2);
add_queue(q,3);
cout<<"pop "<<pop_queue(q)<<endl;
cout<<"pop "<<pop_queue(q)<<endl;
cout<<"pop "<<pop_queue(q)<<endl;
return 0;
}
run:
---------------------------------------------------------------------------------------------------------------