|
刚搞好异步fifo的设计,顶层文件为asynfifo.v
module asynfifo(wrclk,rdata,reclk,wdata,wrst_n,rrst_n,wfull,rempty);
input wrclk,reclk;
input wrst_n,rrst_n;
input [7:0] wdata;
output [7:0] rdata;
output wfull,rempty;
wire [7:0] wptr,rptr;
wire wfulle,remptye;
re_wr_logic re_wr_logic_a(.wrclk(wrclk),.wrst_n(wrst_n),.wfull(wfull),.wptr(wptr),.reclk(reclk),.rrst_n(rrst_n),.rempty(rempty),.rptr(rptr));
duralportram1 duralportram_a(.data(wdata),.wrclock(wrclk),.rdclock(reclk),.rdaddress(rptr),.rden(remptye),.wraddress(wptr),.wren(wfulle),.q(rdata));
assign wfulle=!wfull;
assign remptye=!rempty;
endmodule
子模块re_wr_logic.v(产生读写指针和空满标志)
module re_wr_logic(wrclk,wrst_n,wfull,wptr,reclk,rrst_n,rempty,rptr);
parameter n=8;
input wrclk;
//input wren;//is it needed?
input wrst_n;
output reg wfull;
output reg [n-1:0] wptr;
input reclk;
input rrst_n;
output reg rempty;
output reg [n-1:0] rptr;
reg [7:0] wbin,rbin;
wire [7:0] wbnext,wgnext,rbnext,rgnext;
wire full,empty;
wire dirset,dirrst,dirrst2;
wire high=1;//???ok!
reg direction;
reg wfull2,rempty2;
//reg [n-1:0] wptr0,wptr1,rptr0,rptr1;
always @(posedge wrclk or negedge wrst_n)//generate wptr
if(!wrst_n)
begin
wptr<=8'd0;
wbin<=8'd0;
wfull2<=8'd0;
wfull<=8'd0;
end
else begin
wbin<=wbnext;
wptr<=wgnext;
end
assign wbnext=wfull?wbin:wbin+1;
assign wgnext=(wbnext>>1)^wbnext;
always @(posedge reclk or negedge rrst_n)//generate rptr
if(!rrst_n)
begin
rptr<=0;
rbin<=0;
rempty2<=8'd0;
rempty<=8'd0;
end
else begin
rbin<=rbnext;
rptr<=rgnext;
end
assign rbnext=rempty?rbin:rbin+1;
assign rgnext=(rbnext>>1)^rbnext;
//generate full,wfull,empty,rempty
assign dirset=~((wptr[n-1]^rptr[n-2])&(~(wptr[n-2]^rptr[n-1])));
assign dirrst=(~(wptr[n-1]^rptr[n-2]))&(wptr[n-2]^rptr[n-1]);
assign dirrst2=~(dirrst||wrst_n);
always @(posedge high or negedge dirset or negedge dirrst2)
if(!dirrst2) direction<=0;
else if (!dirset) direction<=1;
else direction<=high;
assign full=~((wptr==rptr)&(~direction));
assign empty=~(direction&(wptr==rptr));
always @(posedge wrclk or negedge full or negedge wrst_n)
if (!wrst_n)
{wfull,wfull2}<=2'b00;
else if(!full)
{wfull,wfull2}<=2'b11;
else
{wfull,wfull2}<={wfull2,~full};
always @(posedge reclk or negedge empty)
if(!empty)
{rempty,rempty2}<=2'b11;
else
{rempty,rempty2}<={rempty2,~empty};
endmodule
子模块duralportram1.v(使用altera的lpm_ram_dp产生)
module duralportram1 (
data,
rdaddress,
rdclock,
rden,
wraddress,
wrclock,
wren,
q);
input [7:0] data;
input [7:0] rdaddress;
input rdclock;
input rden;
input [7:0] wraddress;
input wrclock;
input wren;
output [7:0] q;
wire [7:0] sub_wire0;
wire [7:0] q = sub_wire0[7:0];
altsyncram altsyncram_component (
.wren_a (wren),
.clock0 (wrclock),
.clock1 (rdclock),
.address_a (wraddress),
.address_b (rdaddress),
.rden_b (rden),
.data_a (data),
.q_b (sub_wire0),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.data_b ({8{1'b1}}),
.q_a (),
.wren_b (1'b0));
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone II",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 256,
altsyncram_component.operation_mode = "DUAL_PORT",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.rdcontrol_reg_b = "CLOCK1",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 8,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1;
endmodule
本人编testbench的方法是:先考虑读频率大于写频率的情况,仿真正确,再考虑写频率大于读频率的情况,仿真正确