数据结构之FIFO的一些问题

30 篇文章 0 订阅
16 篇文章 1 订阅

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:



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



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值