实验目的:
最近几天,师兄安排我帮他用FPGA做一个FIFO,用FPGA接收DSP采集和做完信号处理的数据,然后将数据存入FIFO中,ARM再从FIFO中将数据读走,大概的模型如图1所示:
![clip_image002 clip_image002](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222122772-1885347210.jpg)
图1 结构框图
如图1,cs_n为片选信号,DSP和ARM各给FPGA一个片选信号,低电平有效;wr_n为DSP送给FPGA的写使能信号,低电平有效;rd_n为ARM送给FPGA的读使能信号,低电平有效;data为16位位宽的数据总线,DSP给FPGA的输入数据总线(写总线),ARM给FPGA的是输出数据总线(读总线);wr_full是FIFO写满的标志信号,高电平有效;rd_empty是FIFO读空的标志信号,高电平有效。
过程及结果:
(1) FIFO IP核的配置与调用
![fifo的配置1 fifo的配置1](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222124288-2103772814.jpg)
图2 IP核的配置1
![fifo的配置2 fifo的配置2](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222125835-1879465154.jpg)
图3 IP核的配置2
![fifo的配置3 fifo的配置3](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222127804-1221774898.jpg)
图4 IP核的配置3
![fifo的配置4 fifo的配置4](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222129429-1617586211.jpg)
图5 IP核的配置4
FIFO的例化:
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222130554-1086787981.png)
(2)将输入信号多打两拍,稳定输入信号并降低亚稳态发生的概率
1:
//用系统时钟sclk给输入信号多打两拍,稳定输入信号,降低亚稳态出现的概率
2:
//将DSP送来的信号打两拍
3: always @(posedge sclk or negedge rst_n)
4: begin
5:
if(rst_n == 1'b0)
6: {csn_dsp_r, wr_n_r} <= 6'h3f;
7:
else
8: {csn_dsp_r, wr_n_r} <= {{csn_dsp_r[1:0],csn_dsp}, {wr_n_r[1:0],wr_n}};
9: end
10:
11: always @(posedge sclk or negedge rst_n)
12: begin
13:
if(rst_n == 1'b0)
14: data_in_r <= 16'd0;
15:
else
16: data_in_r <= {data_in_r[31:0], data_in};
17: end
18:
19:
//将ARM送来的信号打两拍
20: always @(posedge sclk or negedge rst_n)
21: begin
22:
if(rst_n == 1'b0)
23: {csn_arm_r, rd_n_r} <= 6'h3f;
24:
else
25: {csn_arm_r, rd_n_r} <= {{csn_arm_r[1:0],csn_arm}, {rd_n_r[1:0],rd_n}};
26: end
(3) 读/写操作的控制
1:
//DSP将数据送入FPGA,写入FIFO
2: assign data_in_w = (csn_dsp_r[2]==1'b0 && wr_n_r[2]==1'b0)? data_in_r[47:32]: 16'd0;
3: assign wrreq = (csn_dsp_r[2]==1'b0 && wr_n_r[2]==1'b0)? 1'b1: 1'b0;
4:
//将FIFO中的数据读出送给ARM
5: assign rdreq = (csn_arm_r[2]==1'b0 && rd_n_r[2]==1'b0)? 1'b1: 1'b0;
(4) Testbench的搭建
① 基本的延时语句,包含建立时间、数据采集时间、保持时间、读等待时间等;
② 写数据任务(data_delay应≤系统时钟周期);
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222131929-1418310385.png)
③ 读数据任务;
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222133366-1026044156.png)
④ 整体流程控制;
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222134444-291739593.png)
⑤ 时钟信号和复位信号的初始化。
(5) 仿真结果及分析
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222135710-90480632.png)
图6 Modelsim中查看FIFO的值
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222137991-1864239289.png)
图7 transcript窗口的信息
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222139600-1651926341.png)
图8 仿真波形图1
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222140929-1237170757.png)
图9 仿真波形图2
![image image](http://images2015.cnblogs.com/blog/845088/201603/845088-20160309222142179-29887603.png)
图10 仿真波形图3
如图6所示,通过查看Modelsim中的存储器可看到FIFO中的值,从地址0~255各存储单元上的值也是0~255,与Testbench中设计的一致;如图6所示,transcript窗口显示了从FIFO中读出的数据内容(这里的address不是地址,是变量j的值);图8展示了基本延时单元的延时时间;由图9可知,FIFO写满之后,wr_full信号被拉高,
csn_dsp也随之拉高(Testbench中设计的是拉高),csn_arm被拉低,进入到FIFO读数据状态,读出0地址上的数据0后,wr_full又被拉低了(说明FIFO又可以写数据了);如图10所示,当读到FIFO的255地址时,rd_empty信号被拉高,此时,FIFO已被读空,最后输出的数据是255。