求解惑 | 异步FIFO

目的:如果RAM地址为非2^N,如何用格雷码实现?

64-65 75-76手动修改变化时机,为啥就不能通过呢,自己写的testbench两个代码结果却又是一致的

`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
);


//讀寫使能
wire wenc,renc;
assign wenc = winc & !wfull;
assign renc = rinc & !rempty;

//讀寫地址邏輯
parameter addr_len = $clog2(DEPTH);

reg [addr_len:0] waddr;
reg [addr_len:0] raddr;

    always @(posedge wclk or negedge wrstn)         
        begin                                       
            if(!wrstn)                               
               waddr <='d0; 
            else if (waddr[addr_len-1:0] == DEPTH-1)
               waddr <= {~waddr[addr_len],{addr_len{1'b0}}}; 
            else if(wenc)                           
               waddr <= waddr + 1'b1;               
        end                                         
                                                    

    always @(posedge rclk or negedge rrstn)   
        begin                                
            if(!rrstn)                       
               raddr <='d0;
            else if (raddr[addr_len-1:0] == DEPTH-1)
              raddr <= {~raddr[addr_len],{addr_len{1'b0}}};                   
            else if(renc)           
               raddr <= raddr + 1'b1;                                   
        end

//消除亞穩態; 
//A.格雷碼【addr⊕(addr>>1)】相鄰只變換一個位,可有效防止繼存存捕獲中間態。
//如011-100,變了三位,格雷碼 011-010,只變了一位
//B.常規打二拍
wire [addr_len:0] waddr_gray,raddr_gray;
reg  [addr_len:0] waddr_gray_pat,raddr_gray_pat,waddr_pat1,waddr_pat2,raddr_pat1,raddr_pat2;

    assign waddr_gray = waddr ^ (waddr >> 1 );    
    assign raddr_gray = raddr ^ (raddr >> 1 );

    always @(posedge wclk or negedge wrstn)   
        begin                                
            if(~wrstn) begin
               waddr_gray_pat <='d0;                     
            end                     
            else begin
               waddr_gray_pat <= waddr_gray;    
            end                                    
        end

    always @(posedge rclk or negedge rrstn)   
        begin                                
            if(~rrstn) begin 
               raddr_gray_pat <='d0;                    
            end                     
            else begin   
               raddr_gray_pat <= raddr_gray; 
            end                                    
        end

    always @(posedge wclk or negedge wrstn)   
        begin                                
            if(~wrstn) begin                    
               raddr_pat1 <='d0;
               raddr_pat2 <='d0;
            end                     
            else begin    
               raddr_pat1 <= raddr_gray_pat;
               raddr_pat2 <= raddr_pat1;
            end                                    
        end

    always @(posedge rclk or negedge rrstn)   
        begin                                
            if(~rrstn) begin                    
               waddr_pat1 <='d0;
               waddr_pat2 <='d0;
            end                     
            else begin   
               waddr_pat1 <= waddr_gray_pat;
               waddr_pat2 <= waddr_pat1;
            end                                    
        end

//滿/空判斷
//  要求實時性反應,采用組合邏輯

assign wfull = waddr_gray_pat == {~raddr_pat2[addr_len:addr_len-1],raddr_pat2[addr_len-2:0]};
assign rempty = raddr_gray_pat == waddr_pat2; 

//連綫
wire [addr_len-1:0] waddr_f,raddr_f;
assign waddr_f = waddr[addr_len-1:0];
assign raddr_f = raddr[addr_len-1:0];

dual_port_RAM #(
    .DEPTH(DEPTH),
    .WIDTH(WIDTH)
    )
dual_port_RAM0(
       .wclk    (wclk),
       .wenc    (wenc),
       .waddr   (waddr_f), //
       .wdata   (wdata),       	
       .rclk    (rclk),
       .renc    (renc),
       .raddr   (raddr_f), //
       .rdata 	(rdata)   
         );
endmodule

全部评论

相关推荐

03-12 11:54
门头沟学院 Java
dghyuiok:佬太厉害了,我也27双非,只会黑马商城和苍穹外卖,靠这两个烂大街项目,装成大三面了4个一个没中
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务