`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 reg [WIDTH-1:0] rdata
);
parameter WIDTH_ptr= 5;
parameter WIDTH_addr= 4;
//读写模块
integer i ;
reg [WIDTH-1:0]buff[DEPTH-1:0];
reg [WIDTH_ptr-1:0]w_ptr;
wire [WIDTH_addr-1:0] w_addr;
assign w_addr=w_ptr[WIDTH_addr-1:0];
always@(posedge wclk or negedge wrstn)
begin if(!wrstn)
begin w_ptr<=0;
end
else if(winc&(!wfull))
begin w_ptr<=w_ptr+1;
buff[w_addr]<=wdata;
end
end
reg [WIDTH_ptr-1:0]r_ptr;
wire [WIDTH_addr-1:0] r_addr;
assign r_addr=r_ptr[WIDTH_addr-1:0];
always@(posedge rclk or negedge rrstn)
begin if(!rrstn)
begin r_ptr<=0;
end
else if(rinc&(!rempty))
begin r_ptr<=r_ptr+1;
rdata<=buff[r_addr];
end
end
//指针同步
wire [WIDTH_ptr-1:0]w_gray_ptr;
wire [WIDTH_ptr-1:0]r_gray_ptr;
reg [WIDTH_ptr-1:0]w_gray_ptr_d0;
reg [WIDTH_ptr-1:0]w_gray_ptr_d1;
reg [WIDTH_ptr-1:0]w_gray_ptr_d2;
reg [WIDTH_ptr-1:0]r_gray_ptr_d0;
reg [WIDTH_ptr-1:0]r_gray_ptr_d1;
reg [WIDTH_ptr-1:0]r_gray_ptr_d2;
assign w_gray_ptr=w_ptr^(w_ptr>>1);
assign r_gray_ptr=r_ptr^(r_ptr>>1);
always@(posedge wclk or negedge wrstn) //此在原时钟域打排非必要环节
begin if(!wrstn)
w_gray_ptr_d0<=0;
else w_gray_ptr_d0<=w_gray_ptr;
end
always@(posedge rclk or negedge rrstn)
begin if(!rrstn)
{w_gray_ptr_d2,w_gray_ptr_d1}<=0;
else {w_gray_ptr_d2,w_gray_ptr_d1}<={w_gray_ptr_d1,w_gray_ptr_d0};
end
always@(posedge rclk or negedge rrstn) //此在原时钟域打排非必要环节
begin if(!rrstn)
r_gray_ptr_d0<=0;
else r_gray_ptr_d0<=r_gray_ptr;
end
always@(posedge wclk or negedge wrstn)
begin if(!wrstn)
{r_gray_ptr_d2,r_gray_ptr_d1}<=0;
else {r_gray_ptr_d2,r_gray_ptr_d1}<={r_gray_ptr_d1,r_gray_ptr_d0};
end
//空满标志位产生
assign rempty=(w_gray_ptr_d2==r_gray_ptr_d0);
assign wfull=(r_gray_ptr_d2[WIDTH_ptr-1]!=w_gray_ptr_d0[WIDTH_ptr-1])&(r_gray_ptr_d2[WIDTH_ptr-2]!=w_gray_ptr_d0[WIDTH_ptr-2])&(r_gray_ptr_d2[WIDTH_ptr-3:0]==w_gray_ptr_d0[WIDTH_ptr-3:0]);
endmodule