第1部分 项目需求
任务名称:
两位十进制加、减、乘、除计算器.
任务要求:
实现一个两位十进制数加、减、乘、除运算的计算器,运算数和运算符(加、减、乘、除)由按键来控制。
(实际实现:4位有效数字,包含两位小数点的计算)
第2部分 实现的方式
1、输入输出设计:
输入:
通过扩展板上4*4矩阵按键输入数字及运算符。核心板上K1作为复位按键。
输出:
通过扩展板上8位数码管显示运算数及结果。
核心板上八位LED显示当前运算符,由上至下依次为加、减、乘、除。
核心板上两位数码管作为测试输出,第一位为状态,第二位为按键记录。
2、硬件及软件工具:
硬件为活动活动规定的小脚FPGA套件STEP BaseBoard V4.0,搭载基于Lattice MXO2的小脚丫FPGA核心板。
根据项目需求,软件选择了小脚丫WebIDE及Lattice Diamond作为开发工具。考虑到逻辑部分需要状态机实现,选择了Xmind作为辅助工具绘制流程图。
Lattice Diamond是一款由Lattice Semiconductor开发的EDA(电子设计自动化)软件,用于FPGA(现场可编程门阵列)设计和编程。它提供了完整的FPGA设计流程所需的功能,包括原理图设计、仿真、综合、布局和布线等。
XMind是一款流行的思维导图工具,能够帮助用户更好地理解和表达思维。它以图形化的方式呈现信息,将复杂的信息结构化、可视化,使人们更容易理解和记忆。XMind支持创建多种形式的思维导图,包括树状图、组织图、流程图等,满足用户在不同场景下的需求。
3、模块化设计:
为使代码清晰易读,提高代码的可靠性和可维护性,项目采用了模块化的设计思路。以下是四个主要的模块及其功能:
模块1:数码管扫描(segment_led/ segment_scan)
负责驱动数码管显示,动态刷新运算结果。
模块2:矩阵按键识别(array_keyboard)
实时监测矩阵按键输入,并将输入的数字和运算符传递给核心逻辑模块。
模块3:计算逻辑(logic_calculate)
根据接收到的运算符执行相应的运算,并将结果发送给显示逻辑模块。
模块4:显示逻辑(logic_display)
根据核心逻辑模块的指令,控制LED和数码管的显示内容。
第3部分 功能框图
功能框图主要为状态机逻辑设计。该部分通过Xmind绘制。
该状态机共设计了三个状态(state):S0、S1、S2。复位时回到S0。
S0:未输入符号时的状态。
S1:已输入符号时的状态。
S2:按过等号后的状态。
转换方式非常简单:当按下数字,进入S0;当按下加减乘除,进入S1;当按下等号,进入S2;当按下小数点,进入S0。
状态转换流程
简化代码逻辑图
详细代码流程图
(合并模块已使用相同颜色标出)
第4部分 代码及说明
数码管显示扫描及矩阵按键检测的底层代码直接继承自小脚丫官方例程(网址:www.stepfapga.com),这里也就不再赘述,主要介绍计算部分的逻辑。
以下为部分代码及说明:
1、文件top.v:
该文件为为工程的顶层文件,其中包含了各个硬件功能的例化以及各个模块之间的连线。
LED显示代码:通过0000_0001先右移再左移一位,即可按move_data亮起对应灯,同时在move_data-4'h9 = 0时不亮灯。
always@(move_data)begin
if(move_data>4'h9)
led = ~((8'b1<<(move_data-4'h9))>>1);
else
led = 8'hff;
end
2、文件logic_calculate.v:
该文件为为按键按下后产生的逻辑,即状态机的实现。
状态参数设置:该部分主要用于提高代码可读性(这里实际用到的位宽为2)
parameter S0 = 4'h0; // 未输入符号
parameter S1 = 4'h1; // 已输入符号
parameter S2 = 4'h2; // 按过等号
复位时的初始化:
if(!rst_n) begin
key_data = 4'h0;
move_data = 4'ha;
input_data = 16'h00;
input_dot = 4'h0;
cclt_data = 16'h00;
cclt_dot = 4'h0;
state = S0;
end
对按键返回值进行解码(返回值按照位置编码,该部分将其转换为功能编码),提高代码的可读性及可移植性。
case(key_pulse)
16'h1000: begin key_data = 4'h0; end // 0
16'h0100: begin key_data = 4'h1; end // 1
16'h0200: begin key_data = 4'h2; end // 2
16'h0400: begin key_data = 4'h3; end // 3
16'h0010: begin key_data = 4'h4; end // 4
16'h0020: begin key_data = 4'h5; end // 5
16'h0040: begin key_data = 4'h6; end // 6
16'h0001: begin key_data = 4'h7; end // 7
16'h0002: begin key_data = 4'h8; end // 8
16'h0004: begin key_data = 4'h9; end // 9
16'h8000: begin key_data = 4'ha; end// +
16'h0800: begin key_data = 4'hb; end// -
16'h0080: begin key_data = 4'hc; end// *
16'h0008: begin key_data = 4'hd; end// /
16'h2000: begin key_data = 4'he; end// . (非运算特殊情况)
16'h4000: begin key_data = 4'hf; end// = (state特殊情况)
default: begin key_data = key_data; end //无按键按下时保持无按键按下时保持
endcase
数字输入:(在个位添加,同时移动小数点)
if(key_data<=4'h9) begin
input_data = input_data*10 + key_data;
if(input_dot) input_dot = input_dot+1;
state = S0;
end
计算部分:
首先由于存储方式为整数,小数点另外存储,所以先向右对齐小数点,以便于后续加减计算:
if(input_dot>cclt_dot) begin
//i=0;
repeat(5) begin
if(input_dot>cclt_dot) begin
cclt_data = cclt_data*10;
cclt_dot = cclt_dot +1;
end
end
//cclt_dot = input_dot;
end else begin
//i=0;
repeat(5) begin
if(cclt_dot>input_dot) begin
input_data = input_data*10;
input_dot=input_dot+1;
end
end
end
加减法的运算在对齐了小数点后十分简单,直接进行加减即可:
4'ha: begin
cclt_data = cclt_data + input_data;
end
4'hb: begin
cclt_data = cclt_data - input_data;
end
乘除法则需要单独考虑小数点,分别计算乘除法和小数点,同时要防止由于位数移动导致的溢出:
4'hc: begin
cclt_data = cclt_data * input_data;
if(cclt_dot + input_dot) cclt_dot = cclt_dot + input_dot -1;
else cclt_dot = 4'b0;
end
4'hd: begin
if(input_dot>cclt_dot) begin
//i=0;
repeat(5) begin
if(input_dot>cclt_dot) begin
input_data = input_data/10;
input_dot=input_dot-1;
end
end
cclt_dot = 4'h2;
end else begin
cclt_dot = cclt_dot +2 - input_dot; //+1+1
end
cclt_data = (cclt_data*10) / input_data;
end
如果末尾为0时,去除末位0,小数点后移:
repeat(3) begin
if(cclt_dot>4'b1 && cclt_data%10==0) begin
cclt_dot = cclt_dot -4'b1;
cclt_data = cclt_data /10;
end
end
第5部分 FPGA的资源利用说明
一些配置及说明:
由于初次学习,代码对Lattice LSE并不兼容,使用Lattice LSE做逻辑综合会产生错误且资源占用较高,所以使用 Synplify Pro作为综合工具。
简单介绍:Lattice LSE是Lattice Diamond集成开发环境中的一个综合工具,LSE采用基于规则的综合方法,能够处理复杂的数字电路设计,并且具有较好的稳定性和可靠性。而Synplify Pro则是一款由Synopsys公司开发的FPGA综合工具,与Lattice LSE相比,Synplify Pro采用了基于算法的综合方法,能够处理更广泛的设计问题,并且在处理大型设计时具有更高的性能。
Design Summary:
Number of registers: 224 out of 4635 (5%)
PFU registers: 212 out of 4320 (5%)
PIO registers: 12 out of 315 (4%)
Number of SLICEs: 2011 out of 2160 (93%)
SLICEs as Logic/ROM: 2011 out of 2160 (93%)
SLICEs as RAM: 0 out of 1620 (0%)
SLICEs as Carry: 1143 out of 2160 (53%)
Number of LUT4s: 4021 out of 4320 (93%)
Number used as logic LUTs: 1735
Number used as distributed RAM: 0
Number used as ripple logic: 2286
Number used as shift registers: 0
Number of PIO sites used: 39 + 4(JTAG) out of 105 (41%)
Number of block RAMs: 0 out of 10 (0%)
Number of GSRs: 1 out of 1 (100%)
EFB used : No
JTAG used : No
Readback used : No
Oscillator used : No
Startup used : No
POR : On
Bandgap : On
Number of Power Controller: 0 out of 1 (0%)
Number of Dynamic Bank Controller (BCINRD): 0 out of 6 (0%)
Number of Dynamic Bank Controller (BCLVDSO): 0 out of 1 (0%)
Number of DCCA: 0 out of 8 (0%)
Number of DCMA: 0 out of 2 (0%)
Number of PLLs: 0 out of 2 (0%)
Number of DQSDLLs: 0 out of 2 (0%)
Number of CLKDIVC: 0 out of 4 (0%)
Number of ECLKSYNCA: 0 out of 4 (0%)
Number of ECLKBRIDGECS: 0 out of 2 (0%)