异步fifo

异步FIFO框图

在这里插入图片描述

这里注意空满标志信号需要将读写指针先转换为格雷码在同步到各自时钟域进行比较。

大致步骤如下:
1.读时钟下,读指针按照规则在读时钟下加一计数,写时钟一样。
2.将读写指针转换为格雷码,且在当前时钟域寄存打一拍
3.将转换好的格雷码进行打两拍跨时钟处理。即读指针格雷码在写时钟下打两拍,写指针格雷码在读时钟下打两拍
4,比较产生空满标志。读空即将 同步过来的写指针格雷码与读指针格雷码判断是否相等。
写满即将 同步过来的读指针格雷码与写指针格雷码判断,注意这里是格雷码比较,我们知道二进制码判断满的条件为最高位不等其余位相等,但格雷码判断满的条件为,高两位取反相等,其余位相等
这是因为二进制码转换为格雷码为移位异或得到。

`timescale 1ns/1ns

/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,
					   parameter WIDTH = 8)(
	 input wclk
	,input wenc
	,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。
	,input [WIDTH-1:0] wdata      	//数据写入
	,input rclk
	,input renc
	,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。
	,output reg [WIDTH-1:0] rdata 		//数据输出
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

always @(posedge wclk) begin
	if(wenc)
		RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
	if(renc)
		rdata <= RAM_MEM[raddr];
end 

endmodule  

/***************************************AFIFO*****************************************/
module asyn_fifo#(
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
	input 					wclk	, 
	input 					rclk	,   
	input 					wrstn	,
	input					rrstn	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output wire				wfull	,
	output wire				rempty	,
	output wire [WIDTH-1:0]	rdata
);
    
    
    reg [$clog2(DEPTH):0] rpoint,wpoint;

    
    //写指针
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn)begin
            wpoint <= 0;
        end
        else if(winc&&(!wfull))begin
                wpoint <= wpoint + 1;
            end
    end
    //读指针
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn)begin
            rpoint <= 0;
        end
        else  if(rinc&&(!rempty))begin
                rpoint <= rpoint + 1;
            end
    end    

    wire [$clog2(DEPTH):0]rpoint_g,wpoint_g;    
    assign rpoint_g = (rpoint>>1)^rpoint;//转换为格雷码
    assign wpoint_g = (wpoint>>1)^wpoint;

    
    reg [$clog2(DEPTH):0] rpoint_g_r,wpoint_g_r;//当前时钟寄存一拍
    
   
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn)begin
            wpoint_g_r <= 0;
        end
        else begin
            wpoint_g_r <= wpoint_g;
        end
    end
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn)begin
            rpoint_g_r <= 0;
        end
        else begin
            rpoint_g_r <= rpoint_g;
        end    
        end
    
    reg [$clog2(DEPTH):0] rpoint_g_r_r_r,wpoint_g_r_r_r;//异步时钟打两拍
    reg [$clog2(DEPTH):0] rpoint_g_r_r,wpoint_g_r_r;  
//跨时钟打两拍
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn)begin
            rpoint_g_r_r<=0;
            rpoint_g_r_r_r<=0;
        end
        else begin
            rpoint_g_r_r <= rpoint_g_r;
            rpoint_g_r_r_r <= rpoint_g_r_r;
        end
    end
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn)begin
            wpoint_g_r_r<=0;
            wpoint_g_r_r_r<=0;
        end
        else begin
            wpoint_g_r_r <= wpoint_g_r;
            wpoint_g_r_r_r <= wpoint_g_r_r;
        end
    end
    
    assign rempty = (wpoint_g_r_r_r == rpoint_g_r);
    //assign wfull = (~wpoint_g_r_r[$clog2(DEPTH):$clog2(DEPTH)-1]==rpoint_g[$clog2(DEPTH):$clog2(DEPTH)-1])&&(wpoint_g_r_r[$clog2(DEPTH)-2:0]==rpoint_g[$clog2(DEPTH)-2:0]);
    assign wfull = (wpoint_g_r == {~rpoint_g_r_r_r[$clog2(DEPTH):$clog2(DEPTH)-1],rpoint_g_r_r_r[$clog2(DEPTH)-2:0]});
    dual_port_RAM #(.DEPTH(DEPTH),
                    .WIDTH(WIDTH))
    inst (
        .wclk(wclk),
        .wenc(winc&(~wfull)),
        .waddr(wpoint[$clog2(DEPTH)-1:0]),  //深度对2取对数,得到地址的位宽。
        .wdata(wdata),      	//数据写入
        .rclk(rclk),
        .renc(rinc&(~rempty)),
        .raddr(rpoint[$clog2(DEPTH)-1:0]),  //深度对2取对数,得到地址的位宽。
        .rdata(rdata) 		//数据输出
); 
    
endmodule
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vivado是一款由赛灵思(Xilinx)公司开发的集成电路设计工具。它提供了丰富的功能和工具,用于设计、验证和实现FPGA(现场可编程门阵列)和SoC(片上系统)。异步FIFO(First In First Out)是FIFO的一种类型,用于跨时钟域信号传递。异步FIFO与同步FIFO相比,不要求读写时钟频率相同,因此更加灵活。 在Vivado中,可以使用IP核(Intellectual Property)库中提供的现成的异步FIFO IP来设计异步FIFO。这个IP核包含了异步FIFO的功能模块,可以直接在设计中使用。可以通过Vivado的可视化界面添加异步FIFO IP核,并根据设计需求进行配置。配置完成后,可以生成对应的硬件描述语言(HDL)代码,通过这些代码可以实例化异步FIFO模块。 除了使用Vivado提供的异步FIFO IP核外,您也可以自己编写异步FIFO模块。根据您提供的引用,您可以自编异步FIFO,并根据具体需求选择normal模式或show-ahead模式。在设计完成后,您可以使用Vivado提供的testbench功能对异步FIFO进行仿真,以验证其功能和性能。根据您的描述,测试结果与Xilinx IP一致,这表明您的自编异步FIFO在功能上与Xilinx IP相似。 总结起来,您可以在Vivado中使用现成的异步FIFO IP核,也可以自己编写异步FIFO模块。通过Vivado的可视化界面或者HDL代码进行配置和实例化。最后,使用Vivado的testbench功能对异步FIFO进行仿真,以验证其功能和性能。这样,您就可以在Vivado中设计和实现异步FIFO了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值