题解 | #异步FIFO#
异步FIFO
https://www.nowcoder.com/practice/40246577a1a04c08b3b7f529f9a268cf
`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
);
//write
reg [4:0] count_w, count_w_gray;
reg [4:0] address_r_t, address_r;
wire wen;
always@(posedge wclk or negedge wrstn) begin
if(~wrstn) begin
count_w <= 0;
end
else count_w <= (!wfull && winc)? count_w+1 : count_w;
end
// assign count_w_gray = count_w ^ (count_w>>1);
always@(posedge wclk or negedge wrstn) begin
if(~wrstn) count_w_gray <= 0;
else count_w_gray <= count_w ^ (count_w>>1);
end
always@(posedge wclk or negedge wrstn) begin
if(~wrstn) begin
address_r_t <= 0;
address_r <= 0;
end
else begin
address_r_t <= count_r_gray;
address_r <= address_r_t;
end
end
// assign wfull = ((count_w_gray[4:3]!=address_r[4:3]) && (count_w_gray[2:0] == address_r[2:0]));
assign wfull = ({~count_w_gray[4:3],count_w_gray[2:0]}==address_r);
assign wen = (!wfull && winc);
//read
reg [4:0] count_r, count_r_gray;
reg [4:0] address_w_t, address_w;
wire ren;
always@(posedge rclk or negedge rrstn) begin
if(~rrstn) begin
count_r <= 0;
end
else count_r <= (!rempty && rinc)? count_r+1 : count_r;
end
// assign count_r_gray = count_r ^ (count_r>>1);
always@(posedge rclk or negedge rrstn) begin
if(~rrstn) count_r_gray <= 0;
else count_r_gray <= count_r ^ (count_r>>1);
end
always@(posedge rclk or negedge rrstn) begin
if(~rrstn) begin
address_w_t <= 0;
address_w <= 0;
end
else begin
address_w_t <= count_w_gray;
address_w <= address_w_t;
end
end
assign rempty = (address_w==count_r_gray);
assign ren = (!rempty && rinc);
dual_port_RAM #(.DEPTH(16),.WIDTH(8)) dpram(
.wclk (wclk),
.wenc (wen),
.waddr (count_w[3:0]),
.wdata (wdata),
.rclk (rclk),
.renc (ren),
.raddr (count_r[3:0]),
.rdata (rdata)
);
endmodule
查看6道真题和解析