首页 > 编程知识 正文

sdram和异步fifo,xilinx异步fifo的复位

时间:2023-05-05 06:34:19 阅读:60276 作者:3255

异步FIFO的结构如下图所示。

具体逻辑如下图所示。

空标志逻辑如下图所示。

fifo_async.v代码如下:

` time scale1ns/1 psmodulefifo _ async # (参数addr _ width=5,BIT_WIDTH=8)//DEPTH=32,addr _ width=ath input [ bit _ width-1:0 ] iwritedata,output oWriteFull,input iReadClk,ireadenable//wire wClear; reg [ addr _ width :0 ] rwritepointer=' B0,rReadPointer='b0; //gray code reg [ addr _ width :0 ] rwritecnt=' B0,rReadCnt='b0; //natualbinarycodereg [ addr _ width :0 ] rw2 rpointerfront=' B0,rR2wPointerFront='b0; reg [ addr _ width :0 ] rw2 rpointernext=' B0,rR2wPointerNext='b0; assign wClear=~ iResetN; //thisdualramcontentis32(Depth ) *8(bit width ); Dual_ramdual_ram(.rd_aclr ) wclear )、 rdclock )、 rden ) ireadenable )、 rdaddress ) readpointenter.wr cloclock . wraddress ) rwritepointer [ addr _ width-1:0 ], data ) iwriteclk//outputwriteaddreassalways @ (negedgeiresetets ) IRESETN(beginrwritepointer='B0; rWriteCnt='b0; 嵌入式begin if (可重写) beginrWritePointer={1'b0,rwritecnt [ addr _ width :1 ] } ^ rwritecnt; //convertnatualbinarycodetograycoderwritecnt=rwritecnt (1' B1~owritefull ); endend end//outputreadaddreassalways @ (negedgeiresetnorposedgeireadclk ) beginif (! IRESETN(beginrreadpointer='B0; rReadCnt='b0; EndelseBeginif(ireadenable ) beginrReadPointer={1'b0,rreadcnt [ addr _ width :1 ] } ^ rreadcnt; //convertnatualbinarycodetograycoderreadcnt=rreadcnt (1' B1~oreadempty ); endendendalways @ (negedgeiresetnorposedgeiwriteclk ) beginif (! IRES etn (begin RR2wpointerfront=' B0; rR2wPointerNext='b0; endelsebeginrr2wpointerfront=rreadpointer; RR2wpointernext=RR2wpointerfront; 结束always @ (negedgeiresetnorposedgeireadclk ) beginif (! IRES etn (begin rw2rpointerfront=' B0; rW2rPointerNext='b0; endelsebeginrw2rpointerfront=rwritepointer; rw2rpointernext=rw2rpointerfront; endendassignoreadempty=(rw2 rpointernext==rreadpointer )? 1'b1:1'b0; assignowritefull=(RR2wpointernext [ addr _ width ]=({~rwritepointer [ addr _ width -,rwritepointer[addr_width]

1:0]})?1'b1:1'b0;endmodule

dual_ram.v可由quartus生成,代码如下:

`timescale 1 ps / 1 ps// synopsys translate_onmodule dual_ram (data,rd_aclr,rdaddress,rdclock,rden,wraddress,wrclock,wren,q);input[7:0] data;input rd_aclr;input[4:0] rdaddress;input rdclock;input rden;input[4:0] wraddress;input wrclock;input wren;output[7:0] q;`ifndef ALTERA_RESERVED_QIS// synopsys translate_off`endiftri0 rd_aclr;tri1 rden;tri1 wrclock;tri0 wren;`ifndef ALTERA_RESERVED_QIS// synopsys translate_on`endifwire [7:0] sub_wire0;wire [7:0] q = sub_wire0[7:0];altsyncramaltsyncram_component (.clock0 (wrclock),.wren_a (wren),.aclr1 (rd_aclr),.address_b (rdaddress),.clock1 (rdclock),.address_a (wraddress),.data_a (data),.rden_b (rden),.q_b (sub_wire0),.aclr0 (1'b0),.addressstall_a (1'b0),.addressstall_b (1'b0),.byteena_a (1'b1),.byteena_b (1'b1),.clocken0 (1'b1),.clocken1 (1'b1),.clocken2 (1'b1),.clocken3 (1'b1),.data_b ({8{1'b1}}),.eccstatus (),.q_a (),.rden_a (1'b1),.wren_b (1'b0));defparamaltsyncram_component.address_reg_b = "CLOCK1",altsyncram_component.clock_enable_input_a = "BYPASS",altsyncram_component.clock_enable_input_b = "BYPASS",altsyncram_component.clock_enable_output_a = "BYPASS",altsyncram_component.clock_enable_output_b = "BYPASS",altsyncram_component.intended_device_family = "Cyclone II",altsyncram_component.lpm_type = "altsyncram",altsyncram_component.numwords_a = 32,altsyncram_component.numwords_b = 32,altsyncram_component.operation_mode = "DUAL_PORT",altsyncram_component.outdata_aclr_b = "CLEAR1",altsyncram_component.outdata_reg_b = "CLOCK1",altsyncram_component.power_up_uninitialized = "FALSE",altsyncram_component.rdcontrol_reg_b = "CLOCK1",altsyncram_component.widthad_a = 5,altsyncram_component.widthad_b = 5,altsyncram_component.width_a = 8,altsyncram_component.width_b = 8,altsyncram_component.width_byteena_a = 1;endmodule

fifo_async_tb.v代码如下:

`timescale 1 ns/ 1 psmodule fifo_async_tb();reg iResetN;reg iReadClk;reg iReadEnable;reg iWriteClk;reg [7:0] iWriteData;reg iWriteEnable;wire [7:0] oReadData;wire oReadEmpty;wire oWriteFull;fifo_async fifo_async ( .iResetN( iResetN),.iReadClk( iReadClk),.oReadData( oReadData),.oReadEmpty( oReadEmpty),.iReadEnable( iReadEnable),.iWriteClk( iWriteClk),.iWriteData( iWriteData),.iWriteEnable( iWriteEnable),.oWriteFull( oWriteFull));always @ (*) beginiResetN = 1; iReadEnable = (oReadEmpty == 1'b0)?1'b1:1'b0;iWriteEnable = (oWriteFull == 1'b0)?1'b1:1'b0;end // always// fast writting and slow readinginitial beginforever beginiWriteClk = 0;#10 iWriteClk = 1;#10;endend initial beginiWriteData = 0;#20;forever beginiWriteData = (oWriteFull == 1'b0)?$random:8'b0;#20;endend initial beginforever beginiReadClk = 0;#80 iReadClk = 1;#80;endend // fast reading and slow writting// initial begin// forever begin// iWriteClk = 0;// #40 iWriteClk = 1;// #40;// end// end // initial begin// iWriteData = 0;// #80;// forever begin// iWriteData = (oWriteFull == 1'b0)?$random:8'b0;// #80;// end// end // initial begin// forever begin// iReadClk = 0;// #10 iReadClk = 1;// #10;// end// end endmodule

快读慢写,会产生读空(oReadEmpty),仿真结果如下:

快写慢读,会产生写满(oWriteFull),仿真结果如下:

其它问题:

1、仿真时需要添加quartus的库,以使用双口RAM。

2、FIFO与双口RAM不同,在于FIFO不能指定地址,其地址由计数器(自然二进制码)转Gray码来产生,Gray码翻转的bit较少,从而减少亚稳态。此外,FIFO可以用于同步两个异频/异相时钟。

3、这里的FIFO使用四象限法来设计,将RAM中的地址以最高两位来区分象限,

4、当写指针比读指针落后一个象限时,意味着写指针即将从追上读指针,FIFO处于“可能满”的状态。

5、当读指针比写指针落后一个象限时,意味着读指针即将从追上写指针,FIFO处于“可能空”的状态。

6、利用写时钟给读指针打两拍,以实现同步读指针;同理,利用读时钟给写指针打两拍,以实现同步写指针。

7、在实际应用中,很少使用full和empty标志,而是使用almost full和almost empty,将要满和将要空标志,给RAM的空间留有一定的余量。

8、在实际应用中,往往使用厂家提供的FIFO的IP核,但是我们需要学习异步FIFO的同步思想,所以自己写一下还是很有必要的。

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。