## 用数码管显示的4位加法器 在小脚丫FPGA板上做一个综合性的组合逻辑项目,用4个按键和4个开关作为加法器的输入,将加法以后的结果在2个数码管上显示出来。4位按键和4位开关能够支持的最大输入数字位15,加法以后的最大值30,左侧的数码管,代表十进制数的十位显示的数字为0、1、2、3,右侧的数码管代表十进制的个位显示的数字为0-9。 另外为了观察加法器的每一个进位的状态,使用板上的4个LED分别显示4个进位位的信息。 ### 1. 知识点 * 组合逻辑中的加法器 - 半加器、全加器 * 组合逻辑中的解码器 - BCD码到数码管的显示 * 组合逻辑中的编码器 - 二进制到BCD解码 * Verilog的语法 ### 2. 硬件连接 {{drawio>4bitsadder_seg.png}} 小脚丫FPGA用于实现4位加法器并结果输出的连接示意图 ### 3. Verilog代码 {{drawio>4bitsadder_seg_code_block.png}} module adder_4bits(sw,key,seg_led_1,seg_led_2,led_carry); input [3:0] sw; input [3:0] key; output [8:0] seg_led_1; output [8:0] seg_led_2; output [3:0] led_carry; wire [3:0] input1; wire [3:0] input2; wire [3:0] answer; wire carry_out; wire [3:0] carry; assign input1 = sw; assign input2 = ~key; genvar i; generate for(i=0;i<4;i=i+1) begin: generate_N_bit_Adder if(i==0) half_adder f(input1[0],input2[0],answer[0],carry[0]); else full_adder f(input1[i],input2[i],carry[i-1],answer[i],carry[i]); end assign carry_out = carry[3]; endgenerate assign led_carry = ~carry; wire [4:0] sum; assign sum = {carry_out,answer}; wire [3:0] seg1_input; wire [3:0] seg2_input; binary2bcd b2b(sum,seg1_input,seg2_input); LED display_answer(seg1_input,seg2_input,seg_led_1,seg_led_2); endmodule module half_adder(x,y,s,c); input x,y; output s,c; assign s=x^y; assign c=x&y; endmodule // half adder module full_adder(x,y,c_in,s,c_out); input x,y,c_in; output s,c_out; assign s = (x^y) ^ c_in; assign c_out = (y&c_in)| (x&y) | (x&c_in); endmodule // full_adder module binary2bcd(binary_data,tens,ones); input [4:0] binary_data; output reg [3:0] tens; output reg [3:0] ones; always @* case(binary_data) 5'd0: begin tens = 4'd0; ones = 4'd0; end 5'd1: begin tens = 4'd0; ones = 4'd1; end 5'd2: begin tens = 4'd0; ones = 4'd2; end 5'd3: begin tens = 4'd0; ones = 4'd3; end 5'd4: begin tens = 4'd0; ones = 4'd4; end 5'd5: begin tens = 4'd0; ones = 4'd5; end 5'd6: begin tens = 4'd0; ones = 4'd6; end 5'd7: begin tens = 4'd0; ones = 4'd7; end 5'd8: begin tens = 4'd0; ones = 4'd8; end 5'd9: begin tens = 4'd0; ones = 4'd9; end 5'd10: begin tens = 4'd1; ones = 4'd0; end 5'd11: begin tens = 4'd1; ones = 4'd1; end 5'd12: begin tens = 4'd1; ones = 4'd2; end 5'd13: begin tens = 4'd1; ones = 4'd3; end 5'd14: begin tens = 4'd1; ones = 4'd4; end 5'd15: begin tens = 4'd1; ones = 4'd5; end 5'd16: begin tens = 4'd1; ones = 4'd6; end 5'd17: begin tens = 4'd1; ones = 4'd7; end 5'd18: begin tens = 4'd1; ones = 4'd8; end 5'd19: begin tens = 4'd1; ones = 4'd9; end 5'd20: begin tens = 4'd2; ones = 4'd0; end 5'd21: begin tens = 4'd2; ones = 4'd1; end 5'd22: begin tens = 4'd2; ones = 4'd2; end 5'd23: begin tens = 4'd2; ones = 4'd3; end 5'd24: begin tens = 4'd2; ones = 4'd4; end 5'd25: begin tens = 4'd2; ones = 4'd5; end 5'd26: begin tens = 4'd2; ones = 4'd6; end 5'd27: begin tens = 4'd2; ones = 4'd7; end 5'd28: begin tens = 4'd2; ones = 4'd8; end 5'd29: begin tens = 4'd2; ones = 4'd9; end 5'd30: begin tens = 4'd3; ones = 4'd0; end 5'd31: begin tens = 4'd3; ones = 4'd1; end endcase /* integer i; always @(binary_data) begin tens = 4'd0; ones = 4'd0; for (i=7; i >= 0; i=i-1) begin if (tens>=5) tens = tens +3; if (ones >= 5) ones = ones +3; tens = tens << 1; tens[0] = ones[3]; ones = ones << 1; ones[0] = binary_data[i]; end end */ endmodule // ******************************************************************** // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< // ******************************************************************** // File name : segment.v // Module name : segment // Author : STEP // Description : segment initial // Web : www.stepfpga.com // // -------------------------------------------------------------------- // Code Revision History : // -------------------------------------------------------------------- // Version: |Mod. Date: |Changes Made: // V1.0 |2021/10/08 |Initial ver // -------------------------------------------------------------------- // Module Function:数码管的译码模块初始化 module LED (seg_data_1,seg_data_2,seg_led_1,seg_led_2); input [3:0] seg_data_1; //数码管需要显示0~9十个数字,所以最少需要4位输入做译码 input [3:0] seg_data_2; //小脚丫上第二个数码管 output [8:0] seg_led_1; //在小脚丫上控制一个数码管需要9个信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A output [8:0] seg_led_2; //在小脚丫上第二个数码管的控制信号 MSB~LSB=DIG、DP、G、F、E、D、C、B、A reg [8:0] seg [9:0]; //定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽 initial //在过程块中只能给reg型变量赋值,Verilog中有两种过程块always和initial //initial和always不同,其中语句只执行一次 begin seg[0] = 9'h3f; //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0 seg[1] = 9'h06; //7段显示数字 1 seg[2] = 9'h5b; //7段显示数字 2 seg[3] = 9'h4f; //7段显示数字 3 seg[4] = 9'h66; //7段显示数字 4 seg[5] = 9'h6d; //7段显示数字 5 seg[6] = 9'h7d; //7段显示数字 6 seg[7] = 9'h07; //7段显示数字 7 seg[8] = 9'h7f; //7段显示数字 8 seg[9] = 9'h6f; //7段显示数字 9 end assign seg_led_1 = seg[seg_data_1]; //连续赋值,这样输入不同四位数,就能输出对于译码的9位输出 assign seg_led_2 = seg[seg_data_2]; endmodule ### 4. 管脚分配 {{ :4bitsadder_pinout.jpg |}} 用数码管显示结果的4位加法器的管脚分配图 ### 5. 功能验证