第1个虚拟项目
点灯开启了我们的FPGA之路,那么我们来继续沙盘演练。
用一个虚拟项目,来入门练习,以此步入数字逻辑的大门。
Key Words:FIFO 、SOF 、EOF、计数器、缓存、时序图、方案设计
信号 |
I/O |
位宽 |
描述 |
系统接口信号 |
|||
i_sys_clk |
I |
1 |
系统时钟,125Mhz |
i_rst_n |
I |
1 |
硬复位,低有效 |
输入接口信号 |
|||
i_sop_in |
I |
1 |
输入报文头指示信号,高有效 |
i_eop_in |
I |
1 |
输入报文尾指示信号,高有效 |
i_vld_in |
I |
1 |
输入报文数据有效信号,高有效 |
i_data_in |
I |
8 |
输入报文数据 |
输出接口信号 |
|||
o_sop_out |
O |
1 |
输出报文头指示信号,高有效 |
o_eop_out |
O |
1 |
输出报文尾指示信号,高有效 |
o_vld_out |
O |
1 |
输出报文数据有效信号,高有效 |
o_data_out |
O |
8 |
输出报文数据 |
输入接口时序
输出接口时序
1. 要求输出报文,且报文输出在报文长度输出之后,所以需要先对输入报文进行缓存,根据输入报文的位宽和长度范围,此处选择合适的同步FIFO即可;(如果是IC,那么就需要自己写FIFO,可以参考本博客的FIFO介绍)
这里项目提出了第1个要求,掌握FIFO的使用。
2. 要求输出报文长度,所以需要对输入报文长度进行计数,并将其缓存;
此处有坑,若只用寄存器对长度进行缓存,存在被后续报文长度覆盖的风险,故需要第2个FIFO对报文长度进行缓存。
3. 要求先输出报文长度然后紧跟着输出报文,此处需要对时序进行设计,需要掌握FIFO的读写时序,需要理解fpga的时钟沿采样。
理解:时钟沿采样及数据下一时钟沿变化。
module zmj0001(
input sys_clk,
input rst_n,
input sop_in,
input eop_in,
input vld_in,
input [7:0] data_in,
output sop_out,
output eop_out,
output vld_out,
output [7:0] data_out
);
当然这不是唯一的设计方案,可以先自行考虑设计及验证。
若需完整代码工程,搜索“zmj0001”
项目重难点:
时序设计可以用TimingDesigner软件,简单易用,需要的可以下载。
可以使用计数器来产生数据源data_in;
`timescale 1ns / 1ps
module zmj0001_tb();
reg sys_clk ;
reg rst_n ;
reg [7 :0] data_in ;
reg vld_in ;
reg sop_in ;
reg eop_in ;
reg [11 :0] cnt ;
wire sop_out ;
wire eop_out ;
wire vld_out ;
wire [7:0] data_out ;
initial
begin
sys_clk = 0;
rst_n = 0;
#100
rst_n = 1;
end
always #5 sys_clk = ~sys_clk; //100Mhz
//用计数器来产生data_in
always @(posedge sys_clk or negedge rst_n)begin
if(~rst_n)
cnt <= 12'b0;
else if(cnt > 2048)
cnt <= cnt;
else
cnt <= cnt + 12'b1;
end
always @(posedge sys_clk or negedge rst_n)begin
if(~rst_n)begin
data_in <= 8'b0;
sop_in <= 1'b0;
eop_in <= 1'b0;
vld_in <= 1'b0;
end
else begin
data_in <= 8'b0;
sop_in <= 1'b0;
eop_in <= 1'b0;
vld_in <= 1'b0;
if((cnt > 'd10 && cnt <= 'd60)|(cnt > 'd68 && cnt <= 'd668))begin
data_in <= data_in + 1'b1;
vld_in <= 1'b1;
end
if((cnt == 'd11)|(cnt == 'd69))
sop_in <= 1'b1;
if((cnt == 'd60)|(cnt == 'd668))
eop_in <= 1'b1;
if((cnt == 'd62) | (cnt == 'd63))begin //63 66
data_in <= data_in + 1'b1;
vld_in <= 1'b1;
sop_in <= 1'b1;
eop_in <= 1'b1;
end
end
end
zmj0001 u_zmj0001(
.sys_clk (sys_clk ),
.rst_n (rst_n ),
.sop_in (sop_in ),
.eop_in (eop_in ),
.vld_in (vld_in ),
.data_in (data_in ),
.sop_out (sop_out ),
.eop_out (eop_out ),
.vld_out (vld_out ),
.data_out (data_out )
);
endmodule
具体modelsim使用及与vivado的联合仿真,脚本编写请参考其他博文,后续FPGA其他专栏再考虑写相关内容。
验证时重点关注边界情况。
输入:
共4包数据,长包+超短包+超短包+长包,包间隔均为2clk cycle
data_in : 第1包:1-50的累加数;第2包:1;第3包:1;
输出:
若包间隔<2 clk?
输入:
输出:
可以看到,本设计甚至支持背靠背的超短包输入。
本次虚拟项目旨在用最简单的例子带大家了解数字逻辑设计的一些基本概念,所以很多东西是没有考虑的。比如:
所以,下一篇将沿着这个思路展开,进阶版的虚拟项目,同样可以作为公司的入职培训。
咱们下期见!