您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 基于Verilog利用SRAM设计一个FIFO
1基于Verilog利用SRAM设计一个FIFO专业:电子信息工程班级:电子092学号:姓名:2012年11月23日2一、设计要求:本练习要求同学设计的FIFO为同步FIFO,即对FIFO的读/写使用同一个时钟。该FIFO应当提供用户读使能(fiford)和写使能(fifowr)输入控制信号,并输出指示FIFO状态的非空(nempty)和非满(nfull)信号,FIFO的输入、输出数据使用各自的数据总线:in_data和out_data。下图为FIFO接口示意图。二、FIFO接口的设计思路FIFO的数据读写操作与SRAM的数据读写操作基本上相同,只是FIFO没有地址。所以用SRAM实现FIFO的关键点是如何产生正确的SRAM地址。我们可以借用软件中的方法,将FIFO抽象为环形数组,并用两个指针:读指针(fifo_rp)和写指针(fifo_wp)控制对该环形数组的读写。其中,读指针fifo_rp指向下一次读操作所要读取的单元,并且每完成一次读操作,fifo_rp加一;写指针fifo_wp则指向下一次写操作时存放数据的单元,并且每完成一次写操作,fifo_wp加一。由fifo_rp和fifo_wp的定义易知,当FIFO被读空或写满后,fifo_rp和fifo_wp将指向同一单元,但在读空和写满之前FIFO的状态是不同的,所以如果能区分这两种状态,再通过比较fifo_rp和fifo_wp就可以得到nempty和nfull信号了。下图为FIFO工作状态的示意。在得到nfull和nempty信号后,就需要考虑如何应用这两个信号来控制对FIFO的读写,使得FIFO在被写满后不能再写入,从而防止覆盖原有数据,并且在被读空后也不能再进行读操作,防止读取无效数据。此外,在进SRAM读写操作时,应该注意建立地址、数据和控制信号的先后顺序。一3般情况下,希望对SRAM读写的波形时序如下图所示:即写SRAM时,先建立地址和数据,然后置写使能信号WR有效,在WR保持有效一定时间后,先复位WR,然后释放地址和数据总线。而读取SRAM时,则先建立地址,然后置读使能RD有效,在RD维持有效一定时间后,复位RD,同时读取数据总线上的值,然后再释放地址总线。在进行FIFO操作时,用户一般希望除了没有地址外,其它三个信号的时序关系能保持不变。请同学们在设计FIFO控制信号与SRAM控制信号间逻辑关系时注意这一点。三、FIFO接口的测试在完成一个设计后,需要进行测试以确认设计的正确性和完整性。而要进行测试,就需要编写测试激励和结果检查程序,即测试平台(testbench)。在某些情况下,如果设计的接口能够预先确定,测试平台的编写也可以在设计完成之前就进行,这样做的好处是在设计测试平台的同时也在更进一步深入了解设计要求,有助于理清设计思路,及时发现设计方案的错误。编写测试激励时,除了注意对实际可能存在的各种情况的覆盖外,还要有意针对非正常情况下的操作进行测试。在本练习中,就应当进行在FIFO读空后继续读取、FIFO写满后继续写入、FIFO复位后马上读取等操作的测试。测试激励中通常会有一些复杂操作需要反复进行,如本练习中对FIFO的读写操作。这时可以将这些复杂操作纳入到几个task中,即减小了激励编写的工作量,也使得程序的可读性更好。下面的测试程序给同学们做为参考,希望同学们能先用这段程序测试所设计的FIFO接口,然后编写自己更全面的测试程序。`defineFIFO_SIZE8`include“sram.v”//有的仿真工具不需要加这句,只要sram.v模块编译过就可以了`timescale1ns/1nsmodulet;reg[7:0]in_data;//FIFO数据总线regfiford,fifowr;//FIFO控制信号wire[7:0]out_data;wirenfull,nempty;//FIFO状态信号regclk,rst;wire[7:0]sram_data;//SRAM数据总线wire[10:0]address;//SRAM的地址总线wirerd,wr;//SRAM读写控制信号reg[7:0]data_buf[`FIFO_SIZE:0];//数据缓存,用于结果检查4integerindex;//用于读写data_buf的指针//系统时钟initialclk=0;always#25clk=~clk;//测试激励序列initialbeginfiford=1;fifowr=1;rst=1;#40rst=0;#42rst=1;if(nempty)$display($time,Error:FIFObeempty,nemptyshouldbelow.\n);//连续写FIFOindex=0;repeat(`FIFO_SIZE)begindata_buf[index]=$random;write_fifo(data_buf[index]);index=index+1;endif(nfull)$display($time,Error:FIFOfull,nfullshouldbelow.\n);repeat(2)write_fifo($random);#200//连续读FIFOindex=0;read_fifo_compare(data_buf[index]);if(~nfull)$display($time,Error:FIFOnotfull,nfullshouldbehigh.\n);repeat(`FIFO_SIZE-1)beginindex=index+1;read_fifo_compare(data_buf[index]);endif(nempty)$display($time,Error:FIFObeempty,nemptyshouldbelow.\n);repeat(2)read_fifo_compare(8'bx);reset_fifo;//写后读FIFOrepeat(`FIFO_SIZE*2)begindata_buf[0]=$random;write_fifo(data_buf[0]);read_fifo_compare(data_buf[0]);end//异常操作reset_fifo;read_fifo_compare(8'bx);write_fifo(data_buf[0]);read_fifo_compare(data_buf[0]);$stop;endfifo_interfacefifo_interface(.in_data(in_data),.out_data(out_data),5.fiford(fiford),.fifowr(fifowr),.nfull(nfull),.nempty(nempty),.address(address),.sram_data(sram_data),.rd(rd),.wr(wr),.clk(clk),.rst(rst));sramm1(.Address(address),.Data(sram_data),.SRG(rd),//SRAM读使能.SRE(1'b0),//SRAM片选,低有效.SRW(wr));//SRAM写使能taskwrite_fifo;input[7:0]data;beginin_data=data;#50fifowr=0;//往SRAM中写数#200fifowr=1;#50;endendtasktaskread_fifo_compare;input[7:0]data;begin#50fiford=0;//从SRAM中读数#200fiford=1;if(out_data!=data)$display($time,Error:Dataretrieved(%h)notmatchtheonestored(%h).\n,out_data,data);#50;endendtasktaskreset_fifo;begin#40rst=0;#40rst=1;endendtaskendmodule4)FIFO接口的参考设计FIFO接口的实现有多种方案,下面给出的参考设计只是其中一种。希望同学们在完成自己的设计后,和参考设计做一下比较。`defineSRAM_SIZE8//为减小对FIFO控制器的测试工作量,置SRAM空间为8Byte`timescale1ns/1nsmodulefifo_interface(in_data,//对用户的输入数据总线6out_data,//对用户的输出数据总线,fiford,//FIFO读控制信号,低电平有效fifowr,//FIFO写控制信号,低电平有效nfull,nempty,address,//到SRAM的地址总线sram_data,//到SRAM的双向数据总线rd,//SRAM读使能,低电平有效wr,//SRAM写使能,低电平有效clk,//系统时钟信号rst);//全局复位信号,低电平有效//来自用户的控制输入信号inputfiford,fifowr,clk,rst;//来自用户的数据信号input[7:0]in_data;output[7:0]out_data;reg[7:0]in_data_buf,//输入数据缓冲区out_data_buf;//输出数据缓冲区//输出到用户的状态指示信号outputnfull,nempty;regnfull,nempty;//输出到SRAM的控制信号outputrd,wr;//到SRAM的双向数据总线inout[7:0]sram_data;//输出到SRAM的地址总线output[10:0]address;reg[10:0]address;//InternalRegisterreg[10:0]fifo_wp,//FIFO写指针fifo_rp;//FIFO读指针reg[10:0]fifo_wp_next,//fifo_wp的下一个值fifo_rp_next;//fifo_rp的下一个值regnear_full,near_empty;reg[3:0]state;//SRAM操作状态机寄存器parameteridle='b0000,read_ready='b0100,read='b0101,read_over='b0111,write_ready='b1000,write='b1001,write_over='b1011;//SRAM操作状态机always@(posedgeclkornegedgerst)if(~rst)state=idle;7elsecase(state)idle://等待对FIFO的操作控制信号if(fifowr==0&&nfull)//用户发出写FIFO申请,且FIFO未满state=write_ready;elseif(fiford==0&&nempty)//用户发出读FIFO申请,且FIFO未空state=read_ready;else//没用对FIFO操作的申请state=idle;read_ready://建立SRAM操作所需地址和数据state=read;read://等待用户结束当前读操作if(fiford==1)state=read_over;elsestate=read;read_over://继续给出SRAM地址以保证数据稳定state=idle;write_ready://建立SRAM操作所需地址和数据state=write;write://等待用户结束当前写操作if(fifowr==1)state=write_over;elsestate=write;write_over://继续给出SRAM地址和写入数据以保证数据稳定state=idle;default:state=idle;endcase//产生SRAM操作相关信号assignrd=~state[2];//state为read_ready或read或read_overassignwr=(state==write)?fifowr:1'b1;always@(posedgeclk)if(~fifowr)i
本文标题:基于Verilog利用SRAM设计一个FIFO
链接地址:https://www.777doc.com/doc-4813092 .html