作为一名即将毕业的大四学生,在今年寒假,在了解到由硬禾科技主办的寒假在家一起练活动之后,我感觉到我对FPGA有着一定的兴趣,于是就选择购买了小脚丫FPGA套件STEP BaseBoard V4.0来参加这次的寒假练项目。不过因为我是一个FPGA初学者,之前没有深入的了解过FPGA是什么,对于verilog语言也不是非常的熟悉,所以在这次活动中我一开始选择了比较容易的两位十进制数的加、减、乘、除、运算器中的基本任务要求,但是也没有完成,所以就选择了我能完成的基于Lattice MXO2的小脚丫FPGA核心板 - Type C接口来实现具有启动、停止、递增和清除功能的秒表。接下来就是我这次项目报告的主要内容。
一、项目需求
本次项目的要求是:通过小脚丫FPGA核心板上的2个数码管和轻触按键制作一个秒表,通过按键来控制秒表的功能,并在数码管上显示数值。使用七段显示器作为输出设备,在小脚丫FPGA核心板上创建一个2位数秒表。 秒表应从 0.0 秒计数到 9.9秒,然后翻转,计数值每0.1秒精确更新一次。秒表使用四个按钮输入:开始、停止、增量和清除(重置)。 开始输入使秒表开始以10Hz时钟速率递增(即每0.1秒计数一次); 停止输入使计数器停止递增,但使数码管显示当前计数器值; 每次按下按钮时,增量输入都会导致显示值增加一次,无论按住增量按钮多长时间; 复位/清除输入强制计数器值为零。
二、需求分析
如果想要完成这样一个秒表的设计,首先需要一个0.1Hz的时钟信号来作为秒表小数位的驱动信号,然后需要输入4个信号到小脚丫FPGA核心板上的4个轻触按键上,用来分别实现开始、停止、增量和清除(重置)。而这个项目中最重要的一部分,就是数码管显示部分和秒表的计时功能了。
需要通过逻辑和代码的设计,在开始按键按下后,将输入的0.1Hz信号连接到计数器上,让计数器中储存的数字能够显示在数码管上,并能够实现进位功能。并且当秒表计时到达9.9秒时,能够重置计数器,让数码管的显示归零之后重新计时。停止功能则比较简单,当计数器处于停止状态时,固定数码管的显示就可以了。增加功能与开始功能差不多,当在计数器处于停止状态时,检测到增量按键按下就将计数位加1就能够实现。重置功能就是清空计数器并让计数器处于停止状态即可。
三、实现方式
Lattice MXO2的小脚丫FPGA核心板 - Type C接口的核心结构如上图所示。这块板子的核心器件:Lattice LCMXO2-4000HC-4MG132。由132脚BGA封装,引脚间距0.5mm,芯片尺寸8mm x 8mm,上电瞬时启动,启动时间<1ms,4320个LUT资源, 96Kbit 用户闪存,92Kbit RAM,2+2路PLL+DLL。嵌入式功能块(硬核):一路SPI、一路定时器、2路I2C,支持DDR/DDR2/LPDDR存储器,104个可热插拔I/O,内核电压2.5-3.3V,板载资源:两位7段数码管,两个RGB三色LED,8路用户LED,4路拨码开关,4路按键。
在数码管显示部分,我的代码是这样的:
reg [8:0] seg [9:0]; //digital tube segment
initial
begin
seg[0] = 9'h3f;
seg[1] = 9'h06;
seg[2] = 9'h5b;
seg[3] = 9'h4f;
seg[4] = 9'h66;
seg[5] = 9'h6d;
seg[6] = 9'h7d;
seg[7] = 9'h07;
seg[8] = 9'h7f;
seg[9] = 9'h6f;
end
在这段代码中我定义了一个数组变量,让数码管显示对应的数字,然后在下面的代码中让输出信号输出到核心板上的两个数码管上, led1代表整数位,led2代表小数位。
led1<={seg[sec1][8],1'b1,seg[sec1][6:0]};
led2<=seg[sec2][8:0];
这里led[7]控制的是小数点,所以把它设置成固定值1,让它一直保持显示。
接下来是运行部分的主要代码:
reg [3:0] sec1=4'd0;
reg [3:0] sec2=4'd0; //to store seconds
reg [27:0] counter=28'd0; //second counter
reg running=1'b0; //running state
reg flag=1'b0;
reg inc=1'b1;
在这里我定义了一些变量,用来在运行模块实现秒表计时所需要的各种功能。sec1和sec2用来储存秒数。counter是计数器,通过频率为0.1Hz的时钟信号控制,用来控制计时。running是状态变量,用来控制计数器的工作状态。flag和inc是用来增加按钮是否按下和给计数器的值加1的变量。
然后就是计数器工作状态的主要代码,开始、停止和重置部分比较的简单,在这里直接呈现出来,不做过多赘述。需要注意的一点就是当计数器处于重置状态时,要把sec1和sec2的数值清零再显示在数码管上。
always @(posedge clk) begin
if (reset==1'b0) begin
counter<=28'd0; //counter returns to 0
running<=1'b0; // stop state
sec1<=4'd0;
sec2<=4'd0;
end
else if (start==1'b0) begin
running <= 1'b1; // running state
end
else if (stop==1'b0) begin
running <= 1'b0;
end
稍微复杂一点的是增加状态。在增加状态中,我选择了使用一个flag来检测增加按键是否被按下,inc用来储存值,在检测到增加按键在由按下到松开的过程之后再给计数器counter的值加1。
整个项目中最主要的部分就是计数器的工作部分。在这个项目中,可以把工作内容看成在数码管上以0.1Hz的频率显示00到99,然后让第一个数码管的小数点位一直保持显示即可。基本原理就是使用多个if语句,当秒表的小数位显示到达9时,判断整数位的值,如果整数位不是9的话,则整数位的值加1,小数位清零,如果整数位是9,就把整数位和小数位都清零,重新进行计时。增加部分也是一样,当增加部分被按下并且松开时,就会进行以上的操作。下面是这部分的代码实现:
if (running==1'b1) begin
if (counter==28'd1200000) begin
counter<=28'd0;
if (sec2==4'd9) begin
sec2<=4'd0;
if (sec1==4'd9) begin
sec1<=4'd0;
sec2<=4'd0;
end
else begin
sec1<=sec1+4'd1;
end
end
else begin
sec2<=sec2+4'd1;
end
end
else begin
counter<=counter+28'd1;
end
end
到这里整个代码部分就结束了。这些代码组合到一起就可以实现一个具有启动、停止、递增和清除功能的秒表。然后将各个输入信号和输出信号与核心板上对应的管脚相连接,就能够实现秒表在核心板上的正常运行了。
四、功能框图
根据上面的实现方式中代码的呈现,可以绘制出这个项目的功能框图。
五、FPGA资源利用
在思得普的WebIDE上进行了逻辑综合和管脚分配后,再进行FPGA映射,得到这个具有启动、停止、递增和清除功能的秒表的FPGA资源利用情况,如下图所示:
六、仿真波形
FPGA映射完成后,应当对这个秒表的代码进行仿真检查波形。但是很遗憾,由于我知识水平有限,没有做出来仿真图像。
七、总结
在这次寒假练活动中,通过利用Lattice MXO2的小脚丫FPGA核心板 - Type C接口来实现具有启动、停止、递增和清除功能的秒表,我更加深入的了解到了FPGA和verilog语言。虽然这次完成了项目的基本要求,但是其实还有很多可以改进的空间,比如仿真波形没有弄出来。总之,参加这次寒假练很有收获,也激起了我对于FPGA的兴趣,以后有时间的话会花更多时间来学习FPGA相关知识。