天天看點

資料結構之FIFO的一些問題

FIFO

利用verilog 完成在FPGA中的FIFO的建構

在網上找來一幅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 仿真圖

寫資料

資料結構之FIFO的一些問題

讀資料

資料結構之FIFO的一些問題

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面利用 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:

資料結構之FIFO的一些問題

---------------------------------------------------------------------------------------------------------------