verilog实现异步FIFO代码总结

一、概述

前面的文章总结了FIFO的基本原理和整体设计框图,下面将具体的verilog实现FIFO的代码总结如下。
参考之前的设计框图,主要分成了w_fifo_ctrl、r_fifo_ctrl和sig_dp_ram三个文件(模块)。
在这里插入图片描述

二、写FIFO控制模块

w_fifo_ctrl模块的verilog实现代码如下:

//写FIFO控制模块
module w_fifo_ctrl(
input				wire				w_clk,
input				wire				rst_n,

input				wire				w_en,   //写使能
input				wire [8:0]  r_gaddr,//接收到的读FIFO地址的格雷编码
output			reg  [8:0]	w_addr, //写FIFO地址
output			reg  [8:0]	w_gaddr,//写FIFO地址的格雷编码
output			reg				  w_full  //写满信号
);

wire	[8:0]		w_addr_line;
wire	[8:0]		w_gaddr_line;

reg	  [26:0]	r_gaddr_delay;
//接收到的读FIFO地址的格雷编码再打两拍,降低亚稳态
always@(posedge w_clk or negedge rst_n)
begin
		if(rst_n==1'b0)
				r_gaddr_delay[26:0]<=27'd0;
		else
				r_gaddr_delay[26:0]<={r_gaddr_delay[17:0],r_gaddr[8:0]};
end 
//assign w_full=({~r_gaddr_delay[26],~r_gaddr_delay[25],r_gaddr_delay[24:18]}==w_gaddr[8:0])?1:0;

always@(posedge w_clk or negedge rst_n)
begin
         if(rst_n==1'b0)
                w_full<=1'b0;
         //通过对比读写FIFO的格雷码,生成写满标识。
         else if({~r_gaddr_delay[26],~r_gaddr_delay[25],r_gaddr_delay[24:18]}==w_gaddr[8:0])
                w_full<=1'b1;
         else
                w_full<=1'b0;                  
end

assign w_addr_line=((~w_full)&w_en)+w_addr;

always@(posedge w_clk  or negedge rst_n)
begin
		if(rst_n==1'b0)
				w_addr<=9'd0;
		else
				w_addr<=w_addr_line;
end
//写FIFO地址的格雷编码的组合逻辑
assign w_gaddr_line=w_addr_line^(w_addr_line>>1);

always@(posedge w_clk or negedge rst_n)
begin
		if(rst_n==1'b0)
				w_gaddr<=9'd0;
		else
				w_gaddr<=w_gaddr_line;
end


endmodule

三、读FIFO控制模块

r_fifo_ctrl模块的verilog实现代码如下:

//读FIFO控制模块
module r_fifo_ctrl(
input				wire				r_clk,
input				wire				rst_n,

input				wire				r_en,    //读使能   
input				wire [8:0]  w_gaddr,//接收到的写FIFO地址的格雷编码
output			reg  [8:0]	r_addr,  //读FIFO地址
output			reg  [8:0]	r_gaddr, //读格雷码地址
output			reg				  r_empty  //读空信号
);

wire	[8:0]		r_addr_line;
wire	[8:0]		r_gaddr_line;

reg	  [26:0]	w_gaddr_delay;
//接收到的写FIFO地址的格雷编码再打两拍,降低亚稳态
always@(posedge r_clk or negedge rst_n)
begin
		if(rst_n==1'b0)
				w_gaddr_delay[26:0]<=27'd0;
		else
				w_gaddr_delay[26:0]<={w_gaddr_delay[17:0],w_gaddr[8:0]};
end 

//assign r_empty=(w_gaddr_delay[26:18]==r_gaddr[8:0])?1:0;
//通过对比读写FIFO的格雷码,生成读空标识。
always@(posedge r_clk or negedge rst_n)
begin
         if(rst_n==1'b0)
                r_empty<=1'b0;
         else if(w_gaddr_delay[26:18]==r_gaddr[8:0])
                r_empty<=1'b1;
         else
                r_empty<=1'b0;                  
end

assign r_addr_line=((~r_empty)&r_en)+r_addr;

always@(posedge r_clk  or negedge rst_n)
begin
		if(rst_n==1'b0)
				r_addr<=9'd0;
		else
				r_addr<=r_addr_line;
end
//读FIFO地址的格雷编码组合逻辑
assign r_gaddr_line=r_addr_line^(r_addr_line>>1);

always@(posedge r_clk or negedge rst_n)
begin
		if(rst_n==1'b0)
				r_gaddr<=9'd0;
		else
				r_gaddr<=r_gaddr_line;
end
endmodule

四、XILINX的simple dual port RAM模块

//XILINX的simple dual port RAM模块
module sig_dp_ram(
input			wire				w_clk,
input     wire				w_ram_en,
input			wire	[7:0] w_addr,
input			wire	[7:0]	w_data,

input			wire				r_clk,
input			wire	[7:0]	r_addr,
output		wire	[7:0]	r_data

);

blk_mem_gen_0 blk_mem_gen_0_inst(
  .clka(w_clk),    // input wire clka
  .ena(1'b1),      // input wire ena
  .wea(w_ram_en),      // input wire [0 : 0] wea
  .addra(w_addr),  // input wire [7 : 0] addra
  .dina(w_data),    // input wire [7 : 0] dina
  .clkb(r_clk),    // input wire clkb
  .enb(1'b1),      // input wire enb
  .addrb(r_addr),  // input wire [7 : 0] addrb
  .doutb(r_data)  // output wire [7 : 0] doutb
);

五、顶层模块

module fifo_design_top(
input			wire				w_clk,
input			wire				r_clk,
input			wire				rst_n,

input			wire [7:0]	w_data,
output		wire [7:0]	r_data,

input			wire				w_en,
input			wire				r_en,

output		wire				w_full,
output 		wire				r_empty
);

wire [8:0]	r_gaddr;
wire [8:0]	w_gaddr;
wire [8:0]	r_addr;
wire [8:0]	w_addr;

wire  w_ram_en_wire;
//写RAM的使能信号
assign w_ram_en_wire=(~w_full)&w_en;

w_fifo_ctrl w_fifo_ctrl_inst(
.w_clk  (w_clk),
.rst_n  (rst_n),
.w_en   (w_en),
.r_gaddr(r_gaddr),
.w_addr (w_addr),
.w_gaddr(w_gaddr),
.w_full (w_full)
);

r_fifo_ctrl r_fifo_ctrl_inst(
.r_clk   (r_clk),
.rst_n   (rst_n),
.r_en    (r_en),
.w_gaddr (w_gaddr),
.r_addr  (r_addr),
.r_gaddr (r_gaddr),
.r_empty (r_empty)
);

sig_dp_ram sig_dp_ram_inst(
.w_clk    (w_clk),
.w_ram_en (w_ram_en_wire),
.w_addr   (w_addr[7:0]),
.w_data   (w_data),
.r_clk    (r_clk),
.r_addr   (r_addr[7:0]),
.r_data   (r_data)

);



endmodule

六、testbench

`timescale 1ns/1ns

module tb_fifo_degin_top;

reg w_clk,r_clk,rst_n,w_en,r_en;
reg [7:0]	w_data;

wire [7:0] r_data;
wire w_full,r_empty;


initial
begin
		w_clk=0;
		r_clk=0;
		rst_n=0;
		#140 rst_n=1;
end


initial
begin
	 w_en=0;
	 r_en=0;
	 w_data=0;
	 #300  wdata(257);
	 #123  rdata(257);

end

always #15 w_clk=~w_clk;
always #15 r_clk=~r_clk;

task wdata(len);
			integer i;
			begin
					for(i=0;i<256;i=i+1)
					begin
					    @(posedge w_clk)
					    w_data=i;
					    w_en=1;
					end 
			    @(posedge w_clk)
			    w_data=0;
				w_en=0;
			end
endtask

task rdata(len);
			integer i;
			begin
					for(i=0;i<256;i=i+1)
					begin
					    @(posedge  r_clk)
					    r_en=1;
					end 
			    @(posedge r_clk)
			    r_en=0;
			end
endtask

fifo_design_top fifo_design_top_inst(
.w_clk    (w_clk),
.r_clk    (r_clk),
.rst_n    (rst_n),

.w_data   (w_data),
.r_data   (r_data),

.w_en     (w_en),
.r_en     (r_en),

.w_full   (w_full),
.r_empty  (r_empty)
);

endmodule

七、仿真波形

写满:
在这里插入图片描述
读空:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值