用数码管显示的4位加法器

在小脚丫FPGA板上做一个综合性的组合逻辑项目,用4个按键和4个开关作为加法器的输入,将加法以后的结果在2个数码管上显示出来。4位按键和4位开关能够支持的最大输入数字位15,加法以后的最大值30,左侧的数码管,代表十进制数的十位显示的数字为0、1、2、3,右侧的数码管代表十进制的个位显示的数字为0-9。

另外为了观察加法器的每一个进位的状态,使用板上的4个LED分别显示4个进位位的信息。

1. 知识点

  • 组合逻辑中的加法器 - 半加器、全加器
  • 组合逻辑中的解码器 - BCD码到数码管的显示
  • 组合逻辑中的编码器 - 二进制到BCD解码
  • Verilog的语法

2. 硬件连接

4bitsadder_seg.png

小脚丫FPGA用于实现4位加法器并结果输出的连接示意图

3. Verilog代码

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. 管脚分配

用数码管显示结果的4位加法器的管脚分配图

5. 功能验证