|
Async FIFO
module asfifo (cw,cr,rstn,we,di,re,do,full,empty);
parameter DW=1,AW=1;
parameter DEP=1<<AW;
input rstn,cw,cr,we,re;
input [DW-1:0] di;
output [DW-1:0] do;
output full,empty;
wire [AW-1:0] wc,wc2;
cdc_counter #(AW) uCounter (cw,cr,rstn,we,wc,wc2);
reg [DW-1:0] mem[0:DEP-1];
integer i;
always @(posedge cw or negedge rstn) begin
if(!rstn) for(i=0;i<DEP;i=i+1) mem[i]<={DW{1'b0}};
else if(we) mem[wc]<=di;
end
reg [AW-1:0] rc;
always @(posedge cr or negedge rstn) begin
if(!rstn) rc<={AW{1'b0}};
else if(re) rc<=rc+1;
end
assign do=mem[rc];
wire [AW-1:0] r_w=rc-wc2;
assign empty = (rc==wc2)? 1'b1:1'b0;
assign full = (!empty&&(r_w<5))? 1'b1:1'b0;
endmodule
module cdc_counter (clka,clkb,rstn,en,ac,bc);
parameter DW=1;
input clka,clkb,rstn,en;
output [DW-1:0] ac,bc;
reg [DW-1:0] ac;
reg [ 1:0] ac0;
always @(posedge clka or negedge rstn) begin
if(!rstn) begin
ac <=2'd0;
ac0<=2'd0;
end
else if(en) begin
ac <= ac + 2'd1;
if(ac[0]) ac0[1]<=~ac0[1];
else ac0[0]<=~ac0[0];
end
end
`ifdef CDC_TEST
wire [ 1:0] bc1;
cdc_ff #(2) uCDC_FF(clkb,rstn,ac0,bc1);
`else //CDC_TEST
reg [ 1:0] bc1;
always @(posedge clkb or negedge rstn) begin
if(!rstn) bc1<=2'd0;
else bc1<=ac0;
end
`endif //CDC_TEST
reg [ 1:0] bc2, bc3;
wire [ 1:0] ba={1'b0,(bc2[0]^bc3[0])}+{1'b0,(bc2[1]^bc3[1])};
reg [DW-1:0] bb;
wire [DW-1:0] bc=bb+{{DW-2{1'b0}},ba};
always @(posedge clkb or negedge rstn) begin
if(!rstn) begin
bb<=2'd0; bc3<=2'd0; bc2<=2'd0;
end
else begin
bb<=bc; bc3<=bc2; bc2<=bc1;
end
end
endmodule
`ifdef CDC_TEST
module cdc_ff (clk,rstn,d,q);
parameter DW=1;
input clk,rstn;
input [DW-1:0] d;
output [DW-1:0] q;
integer i;
reg [DW-1:0] q;
reg [DW-1:0] d2;
reg x;
always @(posedge clk or negedge rstn) begin
if(!rstn) begin
q <=0;
x =0;
d2<=0;
end
else begin
for(i=0;i<DW;i=i+1) begin
if(d[i]==d2[i]) q[i]<=d[i];
else q[i]<=x;
x=~x+q[i];
end
d2<=d;
end
end
endmodule
`endif //CDC_TEST |
|