列表

详情


VL45. 异步FIFO

描述

请根据题目中给出的双口RAM代码和接口描述,实现异步FIFO,要求FIFO位宽和深度参数化可配置。

电路的接口如下图所示。

双口RAM端口说明:

端口名

I/O

描述

wclk

input

写数据时钟

wenc

input

写使能

waddr

input

写地址

wdata

input

输入数据

rclk

input

读数据时钟

renc

input

读使能

raddr

input

读地址

rdata

output

输出数据

同步FIFO端口说明:

端口名

I/O

描述

wclk

input

写时钟

rclk

input

读时钟

wrstn

input

写时钟域异步复位

rrstn

input

读时钟域异步复位

winc

input

写使能

rinc

input

读使能

wdata

input

写数据

wfull

output

写满信号

rempty

output

读空信号

rdata

output

读数据

双口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  

输入描述

    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

原站题解

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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
);
parameter											ADDR_SIZE = $clog2(DEPTH);//深度对2取对数,得到写地址的位宽

//-----------------二进制读写地址生成--------------------------------------------------
reg[ADDR_SIZE:0]				waddr_bin;//写地址
reg[ADDR_SIZE:0]				raddr_bin;//读地址

always@(posedge wclk or negedge wrstn)begin
	if(!wrstn) begin
		waddr_bin <= 0 ; 
	end
	else begin
		if(winc && (~wfull)) begin
			waddr_bin <= waddr_bin + 1 ;//每当写时钟沿到来,写使能有效且未写满时,写地址加一
		end
	end
end

always@(posedge rclk or negedge rrstn)begin
	if(!rrstn) begin
		raddr_bin <= 0 ; 
	end
	else begin
		if(rinc && (~rempty)) begin
			raddr_bin <= raddr_bin + 1 ;//每当读时钟沿到来,读使能有效且未读空时,读地址加一
		end
	end
end


//-----------二进制读写地址转换为格雷码读写指针----------------------------------------
wire[ADDR_SIZE:0]			waddr_gray;//格雷码写地址
wire[ADDR_SIZE:0]			raddr_gray;//格雷码读地址
reg[ADDR_SIZE:0]			wptr;//写指针
reg[ADDR_SIZE:0]			rptr;//读指针

assign waddr_gray = waddr_bin ^ (waddr_bin >> 1 ) ;
assign raddr_gray = raddr_bin ^ (raddr_bin >> 1 ) ;

always@(posedge wclk or negedge wrstn)begin
	if(!wrstn) begin
		wptr <= 0 ; 
	end
	else begin
			wptr <= waddr_gray;
	end
end

always@(posedge rclk or negedge rrstn)begin
	if(!rrstn) begin
		rptr <= 0 ; 
	end
	else begin
			rptr <= raddr_gray;
	end
end


//------------格雷码读写指针打两拍同步--------------------------------------------------
reg[ADDR_SIZE:0]									rptr_wclk_buffer;
reg[ADDR_SIZE:0]									rptr_wclk_syn;
reg[ADDR_SIZE:0]									wptr_rclk_buffer;
reg[ADDR_SIZE:0]									wptr_rclk_syn;

always@(posedge wclk or negedge wrstn)begin
	if(!wrstn) begin
		rptr_wclk_buffer <= 0 ; rptr_wclk_syn <= 0 ;
	end
	else begin
		rptr_wclk_buffer <= rptr ;
		rptr_wclk_syn <= rptr_wclk_buffer;
	end
end

always@(posedge rclk or negedge rrstn)begin
	if(!rrstn) begin
		wptr_rclk_buffer <= 0 ; wptr_rclk_syn <= 0 ;
	end
	else begin
		wptr_rclk_buffer <= wptr ;
		wptr_rclk_syn <= wptr_rclk_buffer ;
	end
end


//------------空满判断-----------------------------------------------------------------
assign rempty = (wptr_rclk_syn == rptr ) ;//当读写指针相等时,说明FIFO已读空
assign wfull = (wptr == {~ rptr_wclk_syn[ADDR_SIZE : ADDR_SIZE-1] , rptr_wclk_syn[ADDR_SIZE-2 : 0]}) ;//当读写指针最高两位相反,其余低位都相同时,说明FIFO已写满


//------双口RAM调用------------------------------
wire													wen;//RAM写使能驱动
wire													ren;//RAM读使能驱动

wire [ADDR_SIZE-1:0]  waddr;
wire [ADDR_SIZE-1:0]  raddr;
assign wen = winc & !wfull;
assign ren = rinc & !rempty;
assign waddr = waddr_bin[ADDR_SIZE-1:0];
assign raddr = raddr_bin[ADDR_SIZE-1:0];
 
dual_port_RAM #(.DEPTH(DEPTH),
                .WIDTH(WIDTH)
								) dual_port_RAM(
														    .wclk (wclk),  
														    .wenc (wen),  
														    .waddr(waddr),  //深度对2取对数,得到地址的位宽。
														    .wdata(wdata),           //数据写入
														    .rclk (rclk), 
														    .renc (ren), 
														    .raddr(raddr),   //深度对2取对数,得到地址的位宽。
														    .rdata(rdata)         //数据输出
);
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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    r_en,w_en;
    wire    [4:0]    w_addr,r_addr;
    wire   [$clog2(DEPTH):0] waddr_gray,raddr_gray;
    reg    [4:0]    waddr,raddr;
    reg   [$clog2(DEPTH):0] w_addr_gray,r_addr_gray;
    
    reg    [$clog2(DEPTH):0] w_addr_gray_d1,r_addr_gray_d1,w_addr_gray_d2,r_addr_gray_d2;
    
    assign w_en = winc & ~wfull;
    assign r_en = rinc & !rempty;
    
    always@(posedge wclk or negedge wrstn) begin
        if(!wrstn) begin
            waddr    <= 5'd0;
            w_addr_gray<= 5'd0;
        end
        else begin
            waddr    <= w_addr;
            w_addr_gray<=waddr_gray;
        end
    end
    
    always@(posedge rclk or negedge rrstn) begin
        if(!rrstn) begin
            raddr    <= 5'd0;
            r_addr_gray<= 5'd0;
        end
        else begin
            raddr    <= r_addr;
            r_addr_gray<=raddr_gray;
        end
    end
    
    assign w_addr = waddr+w_en;
    assign r_addr = raddr+r_en;
    assign waddr_gray = waddr ^ (waddr >> 1);
    assign raddr_gray = raddr ^ (raddr >> 1);
    
    always@(posedge rclk or negedge rrstn) begin
        if(!rrstn) begin
            w_addr_gray_d1    <= 4'd0;
            w_addr_gray_d2    <= 4'd0;
        end
        else begin
            w_addr_gray_d1    <= w_addr_gray;
            w_addr_gray_d2    <= w_addr_gray_d1;
        end
    end
    
    always@(posedge wclk or negedge wrstn) begin
        if(!wrstn) begin
            r_addr_gray_d1    <= 4'd0;
            r_addr_gray_d2    <= 4'd0;
        end
        else begin
            r_addr_gray_d1    <= r_addr_gray;
            r_addr_gray_d2    <= r_addr_gray_d1;
        end
    end
    
    assign rempty = r_addr_gray == w_addr_gray_d2;
    assign wfull  = w_addr_gray == {~r_addr_gray_d2[4:3],r_addr_gray_d2[2:0]};
    
    
dual_port_RAM u_dual_port_RAM(
    .wclk     (wclk),
    .wenc     (w_en),
    .waddr    (waddr[$clog2(DEPTH)-1:0]),
    .wdata    (wdata),
    .rclk     (rclk),
    .renc     (r_en),
    .raddr    (raddr[$clog2(DEPTH)-1:0]),
    .rdata    (rdata)
);
    
    
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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
);
    localparam ADDR_WIDTH = $clog2(DEPTH);
    
    // write
    reg [WIDTH-1:0] mem [DEPTH-1:0];
    reg [ADDR_WIDTH:0] waddr;
    wire full;
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn) 
            waddr <= 'b0;
        else if(winc & ~full)
            waddr <= waddr + 1'b1;
        else
            waddr <= waddr;
    end
    
    reg  [ADDR_WIDTH:0] waddr_gray_r;
    wire [ADDR_WIDTH:0] waddr_gray;
    assign waddr_gray = waddr ^ (waddr>>1);
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn) 
            waddr_gray_r <= 'b0;
        else
            waddr_gray_r <= waddr_gray;
    end
    
    reg [ADDR_WIDTH:0] raddr2w [1:0];
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn) begin
            raddr2w[0] <= 'b0;
            raddr2w[1] <= 'b0;
        end
        else begin
            raddr2w[0] <= raddr_gray_r;
            raddr2w[1] <= raddr2w[0];
        end
    end
    
    assign wfull = ({~raddr2w[1][ADDR_WIDTH:ADDR_WIDTH-1],raddr2w[1][ADDR_WIDTH-2:0]} == waddr_gray_r) ? 1'b1 : 1'b0;
    assign full = wfull;

    always@(posedge wclk)begin
        if(winc & ~full)
            mem[waddr[ADDR_WIDTH-1:0]] <= wdata;
    end
            
    
    
    //read
    reg [ADDR_WIDTH:0] raddr;
    wire empty;
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn) 
            raddr <= 'b0;
        else if(rinc & ~empty)
            raddr <= raddr + 1'b1;
        else
            raddr <= raddr;
    end
    
    wire [ADDR_WIDTH:0] raddr_gray;
    reg  [ADDR_WIDTH:0] raddr_gray_r;
    assign raddr_gray = raddr ^ (raddr>>1);
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn) 
            raddr_gray_r <= 'b0;
        else
            raddr_gray_r <= raddr_gray;
    end
    
    reg [ADDR_WIDTH:0] waddr2r [1:0];
    always@(posedge rclk or negedge rrstn)begin
        if(!rrstn) begin
            waddr2r[0] <= 'b0;
            waddr2r[1] <= 'b0;
        end
        else begin
            waddr2r[0] <= waddr_gray_r;
            waddr2r[1] <= waddr2r[0];
        end
    end
    
    assign empty = (waddr2r[1] == raddr_gray_r) ? 1'b1 : 1'b0;
    assign rempty = empty;
    
    reg [WIDTH-1:0] rdata_o;
    always@(posedge rclk)begin
        if(rinc & ~empty)
            rdata_o <= mem[raddr[ADDR_WIDTH-1:0]];
    end

    assign rdata = rdata_o;

    
    
    
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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
);
 
parameter ADDR_WIDTH = $clog2(DEPTH);
 
/**********************addr bin gen*************************/
reg    [ADDR_WIDTH:0]  waddr_bin;
reg    [ADDR_WIDTH:0]  raddr_bin;
 
always @(posedge wclk or negedge wrstn) begin
    if(~wrstn) begin
        waddr_bin <= 'd0;
    end 
    else if(!wfull && winc)begin
        waddr_bin <= waddr_bin + 1'd1;
    end
end
always @(posedge rclk or negedge rrstn) begin
    if(~rrstn) begin
        raddr_bin <= 'd0;
    end 
    else if(!rempty && rinc)begin
        raddr_bin <= raddr_bin + 1'd1;
    end
end
 
/**********************addr gray gen*************************/
wire   [ADDR_WIDTH:0]  waddr_gray;
wire   [ADDR_WIDTH:0]  raddr_gray;
reg    [ADDR_WIDTH:0]  wptr;
reg    [ADDR_WIDTH:0]  rptr;
assign waddr_gray = waddr_bin ^ (waddr_bin>>1);
assign raddr_gray = raddr_bin ^ (raddr_bin>>1);
always @(posedge wclk or negedge wrstn) begin 
    if(~wrstn) begin
        wptr <= 'd0;
    end 
    else begin
        wptr <= waddr_gray;
    end
end
always @(posedge rclk or negedge rrstn) begin 
    if(~rrstn) begin
        rptr <= 'd0;
    end 
    else begin
        rptr <= raddr_gray;
    end
end
/**********************syn addr gray*************************/
reg     [ADDR_WIDTH:0]  wptr_buff;
reg     [ADDR_WIDTH:0]  wptr_syn;
reg     [ADDR_WIDTH:0]  rptr_buff;
reg     [ADDR_WIDTH:0]  rptr_syn;
always @(posedge wclk or negedge wrstn) begin 
    if(~wrstn) begin
        rptr_buff <= 'd0;
        rptr_syn <= 'd0;
    end 
    else begin
        rptr_buff <= rptr;
        rptr_syn <= rptr_buff;
    end
end
always @(posedge rclk or negedge rrstn) begin 
    if(~rrstn) begin
        wptr_buff <= 'd0;
        wptr_syn <= 'd0;
    end 
    else begin
        wptr_buff <= wptr;
        wptr_syn <= wptr_buff;
    end
end
/**********************full empty gen*************************/
assign wfull = (wptr == {~rptr_syn[ADDR_WIDTH:ADDR_WIDTH-1],rptr_syn[ADDR_WIDTH-2:0]});
assign rempty = (rptr == wptr_syn);
 
/**********************RAM*************************/
wire   wen ;
wire    ren ;
wire   wren;//high write
wire [ADDR_WIDTH-1:0]  waddr;
wire [ADDR_WIDTH-1:0]  raddr;
assign wen = winc & !wfull;
assign ren = rinc & !rempty;
assign waddr = waddr_bin[ADDR_WIDTH-1:0];
assign raddr = raddr_bin[ADDR_WIDTH-1:0];
 
dual_port_RAM #(.DEPTH(DEPTH),
                .WIDTH(WIDTH)
)dual_port_RAM(
    .wclk (wclk),  
    .wenc (wen),  
    .waddr(waddr[ADDR_WIDTH-1:0]),  //深度对2取对数,得到地址的位宽。
    .wdata(wdata),           //数据写入
    .rclk (rclk), 
    .renc (ren), 
    .raddr(raddr[ADDR_WIDTH-1:0]),   //深度对2取对数,得到地址的位宽。
    .rdata(rdata)         //数据输出
);
 
endmodule

Verilog 解法, 执行用时: 0ms, 内存消耗: 0KB, 提交时间: 2022-08-06

`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
);
     localparam ADDR_WIDTH = $clog2(DEPTH);
      
    reg [ADDR_WIDTH:0] waddr_bin;
    reg [ADDR_WIDTH:0] raddr_bin;
 
    //数据地址生成部分
    always@(posedge wclk or negedge wrstn) begin
        if(!wrstn)
            waddr_bin <= 0;
        else if(!wfull && winc)
            waddr_bin <= waddr_bin+1;
    end
     
    always@(posedge rclk or negedge rrstn) begin
        if(!rrstn)
            raddr_bin <= 0;
        else if(!rempty && rinc)
            raddr_bin <= raddr_bin+1;
    end
     
     
    //二进制地址转格雷码
     wire [ADDR_WIDTH:0] waddr_gray;
     wire [ADDR_WIDTH:0] raddr_gray;
     reg [ADDR_WIDTH:0] waddr_gray1;
     reg [ADDR_WIDTH:0] raddr_gray1;
      
     assign waddr_gray = waddr_bin^(waddr_bin>>1);
     assign raddr_gray = raddr_bin^(raddr_bin>>1);
    
    always@(posedge wclk or negedge wrstn) begin
        if(!wrstn)
            waddr_gray1 <= 0;
        else
            waddr_gray1 <= waddr_gray;
    end
            
    always@(posedge rclk or negedge rrstn) begin
        if(!rrstn)
            raddr_gray1 <= 0;
        else
            raddr_gray1 <= raddr_gray;
    end
     
     
    //异步跨时钟
    reg [ADDR_WIDTH:0] waddr_gray2;
    reg [ADDR_WIDTH:0] raddr_gray2;
    reg [ADDR_WIDTH:0] waddr_gray3;
    reg [ADDR_WIDTH:0] raddr_gray3;
     
    always@(posedge wclk or negedge wrstn) begin
        if(!wrstn) begin
            raddr_gray2 <= 0;
            raddr_gray3 <= 0;
        end
        else begin
            raddr_gray2 <= raddr_gray1;
            raddr_gray3 <= raddr_gray2;
        end
    end
     
    always@(posedge rclk or negedge rrstn) begin
        if(!rrstn) begin
            waddr_gray2 <= 0;
            waddr_gray3 <= 0;
        end
        else begin
            waddr_gray2 <= waddr_gray1;
            waddr_gray3 <= waddr_gray2;
        end
    end
     
     
    //full与empty判断
    assign wfull = (waddr_gray1 == {~raddr_gray3[ADDR_WIDTH:ADDR_WIDTH-1],raddr_gray3[ADDR_WIDTH-2:0]});
    assign rempty = (raddr_gray1 == waddr_gray3);
     
     
    //RAM例化
    wire [ADDR_WIDTH-1:0] waddr_r;
    wire [ADDR_WIDTH-1:0] raddr_r;
    wire wen;
    wire ren;
     
    assign wen = ~wfull & winc;
    assign ren = ~rempty & rinc;
    assign waddr_r = waddr_bin[ADDR_WIDTH-1:0];
    assign raddr_r = raddr_bin[ADDR_WIDTH-1:0];
     
    
      
      
dual_port_RAM 
    #(
        .DEPTH(DEPTH),
        .WIDTH(WIDTH)
    )
    dual_port_RAM_U0
    (
        .wclk(wclk),
        .wenc(wen),
        .waddr(waddr_r),  //深度对2取对数,得到地址的位宽。
        .wdata(wdata),        //数据写入
        .rclk(rclk),
        .renc(ren),
        .raddr(raddr_r),  //深度对2取对数,得到地址的位宽。
        .rdata(rdata)      //数据输出
);   
     

    
endmodule

上一题