## 乘法器
### 1. 设计需求
- 掌握乘法器的工作原理
- 掌握组合逻辑的设计
- 基于小脚丫STEP FPGA Base Board开发平台实现乘法器的设计
### 2. 原理
FPGA实现乘法器的设计可以有多种方法,可以设计为串行的和并行的:
* 串行乘法器:速度比较慢、时延大,完成同样位宽的乘法器资源占用最少。
* 并行乘法器:相对串行乘法器,速度更快,时延小,需要更多的硬件资源。
串行乘法器需要一个寄存器,每次时钟触发完成乘数中的一位与被乘数之间的运算,同时加入寄存器中,如此乘数的位宽是多少就需要至少多少个时钟的时延完成乘法器的运算。并行乘法器为了降低时延,需要乘数位宽中的每一位同时完成与被乘数之间的运算,这样就需要乘数位宽数个寄存器,然后将所有寄存器的值相加得到乘法结果。
0 x 0 = 0
1 x 0 = 0
0 x 1 = 0
1 x 1 = 1
{{ :binary-multiplication.jpeg |}}
{{ :2-bit-multiplication-new.jpeg |}}
{{ :4-bit-binary-multiplier.jpeg |}}
{{ :4-bit-multiplication-by-shift-method.jpeg |}}
### 4. FPGA实现
{{drawio>multiplication_show_block.png}}
结合实验平台[[STEP-Baseboard]]的硬件配置,我们使用4路拨码开关表示乘数,4路按键开关表示被乘数,8个LED灯作为乘法器的输出
{{:图11.拨码模块电路连接.png?500 |拨码模块电路连接}}
{{ :图10.LED模块电路连接.png?500|LED模块电路连接}}
{{:图9.按键模块电路连接.png?500|按键模块电路连接}}
### 5. 代码设计
设计文件
{{ :流水灯程序设计.jpg |流水灯程序设计}}
为了实现对8个LED的控制,我们设计了25位的计数器cnt进行1s周期的循环计数,同时我们定义了一个3位寄存器led_cnt作为状态机的状态控制流水灯的闪烁。状态机共有8个状态,每一个状态对应点亮一个LED灯。
首先是计数器的设计,计数器的计数范围为0~CNT_NUM-1,为了实现每个LED灯1秒的点亮时间,设计文件代码中我们定义参数CNT_NUM为25000000,但是在仿真文件调用设计文件时,为了方便仿真,我们会将参数CNT_NUM重新赋值为10.
reg [24:0] cnt = 25'd0;
always@(posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
cnt <= 25'd0;
end else if(cnt>=CNT_NUM-1) begin
cnt <= 25'd0;
end else begin
cnt <= cnt + 25'd1;
end
end
然后我们需要对状态机的状态进行控制,使得作为状态的寄存器led_cnt实现从0到7的循环加一操作。
reg [2:0] led_cnt = 3'd0;
always@(posedge clk_in or negedge rst_n_in) begin
if(!rst_n_in) begin
led_cnt <= 3'd0;
end else if(cnt==CNT_NUM-1) begin
if(led_cnt==3'd7) led_cnt <= 3'd0;
else led_cnt <= led_cnt + 3'd1;
end
end
最后是组合逻辑,根据led_cnt的不同状态控制不同的LED点亮。
always@(led_cnt) begin
case(led_cnt)
3'd0: led_out = 8'b1111_1110;
3'd1: led_out = 8'b1111_1101;
3'd2: led_out = 8'b1111_1011;
3'd3: led_out = 8'b1111_0111;
3'd4: led_out = 8'b1110_1111;
3'd5: led_out = 8'b1101_1111;
3'd6: led_out = 8'b1011_1111;
3'd7: led_out = 8'b0111_1111;
default: led_out = 8'b1111_1111;
endcase
end
测试文件
测试文件中我们需要对设计文件中的参数CNT_NUM进行重新赋值
parameter CNT_NUM = 10;
Water_led #(.CNT_NUM(CNT_NUM))
Water_led_uut
(
.clk_in(sys_clk),
.rst_n_in(sys_rst_n),
.led_out(led_out)
);
引脚分配如下:
^ 管脚名称 | clk_in| rst_n_in | led_out[0] |led_out[1] |led_out[2] |led_out[3] |led_out[4] |led_out[5] |led_out[6] |led_out[7] |
^ FPGA管脚 | C1 | A2 |B14 |C14 |E14 |F14 |G14 |J14 |K14 |L14 |
仿真结果
{{:流水灯仿真.jpg|流水灯仿真}}
资源报告
^ 资源 | 数量 | 比例 | 说明 |
^ LUTs | 27 | 4% | |
^ 寄存器 | 28 | 2% | |
^ 存储器 | 0 | 0% | |
^ IO管脚 | 10 | | |
^ 时钟频率 | 25MHz | | |
知识点
* 分频设计
* 时序控制
* 简单状态机
参考文档
* [[点亮led灯]]
* {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}}
相关文档
^ **文件名称** | **功能** |
^ **[[Water_led.v]]** | **流水灯** |
^ **[[Water_led_test.v]]** | **测试文件** |
### 5. 参考资料
* [[https://www.electronicshub.org/binary-multiplication/|二进制乘法器]]