合工大计组实验六 8位乘法器设计与实现

目录

实验目标及任务

实验内容与结果记录

步骤1-2:

步骤3-5:

实验目标及任务

实验目标:

1、了解8位有符号、无符号乘法器的实现原理。

2、使用Verilog实现8位无符号乘法器和有符号乘法器。

实验任务:

1、设计无符号乘法器,将两个8位无符号数相乘,得到一个16位无符号数。

2、设计有符号乘法器,将两个8位有符号数相乘,得到一个16位有符号数。

3、设计按键输入转换电路,设计七段显示器显示和控制电路:  通过8个按键输入两个4位的二进制乘数A和B,两个乘数和乘积的结果,分别送给多个七段显示器进行显示。

实验内容与结果记录

(在完成实验基础上额外完成步骤3-5 )

步骤1-2:

源代码:

module MULTU(
input clk,    //乘法器时钟信号
input reset,
input [ 15:0]  a,      //输入a(被乘数)
input [15:0]  b,      //输入b(乘数)
output [ 31:0]  z     //乘积输出z
);
reg [ 31:0 ]  temp;    //申请寄存器
reg [ 31:0 ]  stored0;
reg [ 31:0 ]  stored1;
reg [ 31:0 ]  stored2;
reg [ 31:0 ]  stored3;
reg [31 :0]  stored4;
reg [31 :0]  stored5 ;
reg [ 31:0 ]  stored6;
reg [ 31:0 ]  stored7;
reg [ 31:0 ]  stored8;
reg [ 31:0 ]  stored9;
reg [ 31:0 ]  stored10;
reg [ 31:0 ]  stored11;
reg [31 :0]  stored12;
reg [31 :0]  stored13 ;
reg [ 31:0 ]  stored14;
reg [ 31:0 ]  stored15;
reg [ 31:0 ]  add0_1;
reg [ 31:0 ]  add2_3;
reg [ 31:0 ]  add4_5;
reg [ 31:0 ]  add6_7;
reg [ 31:0 ]  add8_9;
reg [ 31:0 ]  add10_11;
reg [ 31:0 ]  add12_13;
reg [ 31:0 ]  add14_15;
reg [ 31:0 ]  add0t1_2t3;
reg [ 31:0 ]  add4t5_6t7;
reg [ 31:0 ]  add8t9_10t11;
reg [ 31:0 ]  add12t13_14t15;
reg [ 31:0 ]  add0t3_4t7;
reg [ 31:0 ]  add8t11_12t15;
always @( posedge clk or negedge reset)
begin
if(reset) begin    //reset 置零
temp <= 0;
stored0 <= 0 ;
stored1 <= 0 ;
stored2<= 0 ;
stored3<= 0 ;
stored4 <= 0 ;
stored5<= 0 ;
stored6<= 0 ;
stored7 <= 0 ;
stored8 <= 0 ;
stored9 <= 0 ;
stored10<= 0 ;
stored11<= 0 ;
stored12 <= 0 ;
stored13<= 0 ;
stored14<= 0 ;
stored15 <= 0 ;
add0_1<= 0;
add2_3<= 0;
add4_5 <= 0;
add6_7 <= 0;
add8_9<= 0;
add10_11<= 0;
add12_13 <= 0;
add14_15<= 0;
add0t1_2t3<= 0;
add4t5_6t7<= 0;
add8t9_10t11<= 0;
add12t13_14t15<= 0;
add0t3_4t7<= 0;
add8t11_12t15<= 0;
end
else begin      //通过字符拼接方式表示出中间相乘值,并相加
stored0=(b[0]?{16'b0,a}:32'b0);
stored1=(b[1]?{15'b0,a,1'b0}:32'b0);
stored2=(b[2]?{14'b0,a,2'b0}:32'b0);
stored3=(b[3]?{13'b0,a,3'b0}:32'b0);
stored4=(b[4]?{12'b0,a,4'b0}:32'b0);
stored5=(b[5]?{11'b0,a,5'b0}:32'b0);
stored6=(b[6]?{10'b0,a,6'b0}:32'b0);
stored7=(b[7]?{9'b0,a,7'b0}:32'b0);
stored8=(b[8]?{8'b0,a,8'b0}:32'b0);
stored9=(b[9]?{7'b0,a,9'b0}:32'b0);
stored10=(b[10]?{6'b0,a,10'b0}:32'b0);
stored11=(b[11]?{5'b0,a,11'b0}:32'b0);
stored12=(b[12]?{4'b0,a,12'b0}:32'b0);
stored13=(b[13]?{3'b0,a,13'b0}:32'b0);
stored14=(b[14]?{2'b0,a,14'b0}:32'b0);
stored15=(b[15]?{1'b0,a,15'b0}:32'b0);
add0_1= (stored0 + stored1) ;
add2_3= (stored2 + stored3) ;
add4_5= (stored4 + stored5) ;
add6_7= (stored6 + stored7);
add8_9= (stored8 + stored9 );
add10_11= (stored10 + stored11) ;
add12_13= (stored12 + stored13 );
add14_15= (stored14 + stored15);
add0t1_2t3=( add0_1 + add2_3);
add4t5_6t7= (add4_5 + add6_7);
add8t9_10t11=( add8_9 + add10_11);
add12t13_14t15=( add12_13 + add14_15);
add0t3_4t7= (add0t1_2t3+add4t5_6t7);
add8t11_12t15= (add8t9_10t11+add12t13_14t15);
temp=(add0t3_4t7+add8t11_12t15);
end
end
assign z =temp;
endmodule

激励文件:

module MULTUTEST;

parameter CLKPER = 10; //时钟

reg clk;
reg reset;
reg [15:0] a, b;
wire [31:0] z;

//初始化
MULTU multu1(
    .clk(clk), 
    .reset(reset), 
    .a(a), 
    .b(b), 
    .z(z)
    );

// 时钟
always begin
    #CLKPER clk = ~clk;
end

// 输入input
initial begin
    clk = 0;
    reset = 1;
    #CLKPER;
    reset = 0;
    #CLKPER;
    #CLKPER;
    a = 16'd4; b = 16'd4;  //Test case 1: Multiplication of 4*4
    #CLKPER;
    #CLKPER;
    a = 16'd10; b = 16'd15;  //Test case 2: Multiplication of 10*15
    #CLKPER;
    #CLKPER;
    a = 16'd255; b = 16'd255;  //Test case 3: Multiplication of 255*255
    #CLKPER;
    #CLKPER;
    a = 16'd1024; b = 16'd2048;  //Test case 4: Multiplication of 1024*2048
    #CLKPER;
    $finish;
end

endmodule

模拟仿真图像:

(步骤1-2不需要下载到开发板,因此没有引脚约束文件和图片结果)

步骤3-5:

源代码:(模拟仿真时注意看最后两行的注释)

module MULTU(
input clk,    //乘法器时钟信号
input [3:0]  a,      //输入a(被乘数)
input [3:0]  b,      //输入b(乘数)
output [7:0]  z     //乘积输出z
);
reg [ 7:0 ]  temp;    //申请寄存器
reg [ 7:0 ]  stored0;
reg [ 7:0 ]  stored1;
reg [ 7:0 ]  stored2;
reg [ 7:0 ]  stored3;
reg [ 7:0 ]  add0_1;
reg [ 7:0 ]  add2_3;
always @( posedge clk)
begin
stored0= b[0]?{4'b0,a}:8'b0;
stored1= b[1]?{3'b0,a,1'b0}:8'b0;
stored2= b[2]?{2'b0,a,2'b0}:8'b0;
stored3= b[3]?{1'b0,a,3'b0}:8'b0;
add0_1= stored1 + stored0 ;
add2_3= stored2 + stored3 ;
temp= add0_1 + add2_3;
end
assign z = temp;
endmodule

//控制两个数码管动态显示的模块。seg0[3:0]和seg1[3:0]分别是两个8421BCD码。
//如果是控制8个数码管显示,需要修改信号an为8位,作为8个数码管的位选控制。
//现在已完成修改8位
module    ShowTwoSeg7(input clk,input [3:0] seg0,input [3:0] seg1,
input [3:0] seg2,input [3:0] seg3,input [3:0] seg4,input [3:0] seg5,
input [3:0] seg6,input [3:0] seg7,output reg [7:0]  an, output reg [7:0]  seg,output reg [7:0] segg);
reg [2:0]state;
reg [3:0]  bcd;
    always @(posedge clk) begin
        state <= state + 1;
    end 
    
    always @(*) begin
        case(state)
            3'b000: begin
                an = 8'b00000001;
                bcd = seg7;
            end
            3'b001: begin
                an = 8'b00000010;
                bcd = seg6;
            end
            3'b010: begin
                an = 8'b00000100;
                bcd = seg5;
            end
            3'b011: begin
                an = 8'b00001000;
                bcd = seg4;
            end
            3'b100: begin
                an = 8'b00010000;
                bcd = seg3;
            end
            3'b101: begin
                an = 8'b00100000;
                bcd = seg2;
            end
            3'b110: begin
                an = 8'b01000000;
                bcd = seg1;
            end
            3'b111: begin
                an = 8'b10000000;
                bcd = seg0;
            end
        endcase
end
//8421BCD码bcd与一位数码管的8段A、B、C、D、E、F、G、DP之间的对应关系
    always @(*) begin
        if(an> 8'b00001000) begin//可能遇到seg一个信号不能同时绑定左右两边数码管,多做一份segg作为右边数码管信号    
            case(bcd) 
                4'h0: seg = 8'hfc;
                4'h1: seg = 8'h60;
                4'h2: seg = 8'hda;
                4'h3: seg = 8'hf2;
                4'h4: seg = 8'h66;
                4'h5: seg = 8'hb6;
                4'h6: seg = 8'hbe;
                4'h7: seg = 8'he0;
                4'h8: seg = 8'hfe;
                4'h9: seg = 8'hf6;
           //      4'ha: seg = 8'hee;
           //     4'hb: seg = 8'h3e;
           //     4'hc: seg = 8'h9c;
            //    4'hd: seg = 8'h7a;
            //    4'he: seg = 8'h9e;
            //    4'hf: seg = 8'h8e;
                default: seg = 8'h00;      //八段全熄灭  
            endcase
        end
        else begin
            case(bcd) 
                4'h0: segg = 8'hfc;
                4'h1: segg = 8'h60;
                4'h2: segg = 8'hda;
                4'h3: segg = 8'hf2;
                4'h4: segg = 8'h66;
                4'h5: segg = 8'hb6;
                4'h6: segg = 8'hbe;
                4'h7: segg = 8'he0;
                4'h8: segg = 8'hfe;
                4'h9: segg = 8'hf6;
           //      4'ha: seg = 8'hee;
           //     4'hb: seg = 8'h3e;
           //     4'hc: seg = 8'h9c;
            //    4'hd: seg = 8'h7a;
            //    4'he: seg = 8'h9e;
            //    4'hf: seg = 8'h8e;
                default: segg = 8'h00;      //八段全熄灭  
            endcase
        end
    end
initial begin
state=0;
end
endmodule



//4位二进制转8421
module bin_to_bcd(
    input [3:0] bin, // 输入的二进制数
    output reg [3:0] tens, // BCD码的十位
    output reg [3:0] ones // BCD码的个位
);
    // 此处实现二进制到BCD的转换
    always @(bin) begin
        // 初始化BCD数字
        tens = 0;
        ones = 0;
        // 计算十位和个位
        if (bin > 9) begin
            tens = bin / 10;
            ones = bin % 10;
        end else begin
            ones = bin;
        end
    end
endmodule



//8位二进制转8421,给乘积用的
module bin_to_bcd_eight(
    input [7:0] bin, // 输入的二进制数
    output reg [3:0] thous,//BCD码的千位
    output reg [3:0] huns,//BCD码的百位
    output reg [3:0] tens, // BCD码的十位
    output reg [3:0] ones // BCD码的个位
);
    // 此处实现二进制到BCD的转换
    always @(bin) begin
        // 初始化BCD数字
        thous = 0;
        huns = 0;
        tens = 0;
        ones = 0;
        // 计算百位十位个位,因为最多15*15=225,压根没必要计算千位
        if (bin > 99) begin
            huns = bin / 100;
            tens = (bin / 10) % 10;
            ones = bin % 10;
        end 
        else if (bin > 9) begin
            tens = bin / 10;
            ones = bin % 10;
        end
        else begin
            ones = bin;
        end
    end
endmodule



//数码管动态扫描所需要的时钟模块
module clk_div(
    input clk0,
    output reg clk
    );  
    parameter N = 32'd51200,  WIDTH = 32 - 1;
    reg [WIDTH : 0]  number = 0;
    
    always @(posedge clk0) begin//原本给的代码监听应该写错了,是clk0才对
        if (number == N - 1) begin
           number <=0;
            clk <= ~clk;
        end
        else begin
            number <= number + 1;
        end
    end
initial begin//这里需要补充初始化clk,不然全程X,反转都是X
clk=0;
end
endmodule



module fourbit_bcd(clk,A,B,an,seg,segg);
    input clk;      // 输入时钟,需要分频后进行动态扫描控制。
    input[3:0]  A;       //   输入乘数A
    input[3:0]  B;      //输入乘数B
    //output reg an1, an2;    // 显示乘数A和乘数B的两个数码管的位选控制端
    output wire[7:0]  an;    // 八个数码管的位选控制端
    wire[7:0]  mul1,mul2; // 乘数A和乘数B。乘数A的十、个位分时送给mul1,B给mul2
    wire[15:0]  mul; //乘积的千、百、十、个位分时送给mul。进行动态显示
    wire[7:0]  result;   //乘积
    wire clk_digit;//数码管动态扫描所需时钟
    output wire[7:0] seg;//段选信号
    output wire[7:0] segg;//右侧数码管段选信号
    
    //乘数转8421
    bin_to_bcd d1(.bin(A),.tens(mul1[7:4]),.ones(mul1[3:0]));
    bin_to_bcd d2(.bin(B),.tens(mul2[7:4]),.ones(mul2[3:0]));
    //获取乘积
    MULTU multu(.clk(clk),.a(A),.b(B),.z(result));
     //乘积转8421
     bin_to_bcd_eight res(.bin(result),.thous(mul[15:12]),.huns(mul[11:8]),.tens(mul[7:4]),.ones(mul[3:0]));
    //获取数码管动态扫描所需clk_digit
    clk_div clkdiv1(.clk0(clk),.clk(clk_digit));  
    //获取数码管段选信号
    ShowTwoSeg7 da1(.clk(clk_digit),.seg0(mul1[7:4]),.seg1(mul1[3:0]),.seg2(mul2[7:4]),.seg3(mul2[3:0]),
    .seg4(mul[15:12]),.seg5(mul[11:8]),.seg6(mul[7:4]),.seg7(mul[3:0]),.an(an),.seg(seg),.segg(segg));
//(这里上面的.clk(clk_digit),仿真时使用clk才能看到效果,因为clk_digit是ms级的时钟,
//仿真是ns级的,用clk_digit仿真时看不出效果,所以仿真时可以暂时用clk代替。)
endmodule

激励文件:

module fourbit_bcd_tb();
parameter CLKPER = 10; //时钟
reg clk;
reg [3:0] A;
reg [3:0] B;
wire [7:0] an;
wire [7:0] seg;//段选信号
wire [7:0] segg;//右侧数码管段选信号

//初始化
fourbit_bcd fb(
    .clk(clk),
    .A(A),
    .B(B),
    .an(an),
    .seg(seg),
    .segg(segg)
);
// 时钟
always begin
    #CLKPER clk = ~clk;
end

initial begin
    clk = 0;
    A=4'b0010;//2*2
    B=4'b0010;
    #CLKPER;
    #CLKPER;
    #CLKPER;
    A=4'b0100;//4*4
    B=4'b0100;
    #CLKPER;
    #CLKPER;
    #CLKPER;
    A=4'b1011;//11*11
    B=4'b1011;
    #CLKPER;
    #CLKPER;
    #CLKPER;

end
endmodule

引脚约束文件:

set_property PACKAGE_PIN P17 [get_ports clk]
set_property PACKAGE_PIN P2 [get_ports {A[0]}] 
set_property PACKAGE_PIN P3 [get_ports {A[1]}] 
 set_property PACKAGE_PIN P4 [get_ports {A[2]}]  
 set_property PACKAGE_PIN P5 [get_ports {A[3]}]  
 set_property PACKAGE_PIN R1 [get_ports {B[0]}] 
set_property PACKAGE_PIN N4 [get_ports {B[1]}] 
 set_property PACKAGE_PIN M4 [get_ports {B[2]}]  
 set_property PACKAGE_PIN R2 [get_ports {B[3]}] 
set_property PACKAGE_PIN G2 [get_ports an[7]]
set_property PACKAGE_PIN C2 [get_ports an[6]]
set_property PACKAGE_PIN C1 [get_ports an[5]]
set_property PACKAGE_PIN H1 [get_ports an[4]]
set_property PACKAGE_PIN G1 [get_ports an[3]]
set_property PACKAGE_PIN F1 [get_ports an[2]]
set_property PACKAGE_PIN E1 [get_ports an[1]]
set_property PACKAGE_PIN G6 [get_ports an[0]]
set_property PACKAGE_PIN B4 [get_ports {seg[7]}]
set_property PACKAGE_PIN A4 [get_ports {seg[6]}]
set_property PACKAGE_PIN A3 [get_ports {seg[5]}]
set_property PACKAGE_PIN B1 [get_ports {seg[4]}]
set_property PACKAGE_PIN A1 [get_ports {seg[3]}]
set_property PACKAGE_PIN B3 [get_ports {seg[2]}]
set_property PACKAGE_PIN B2 [get_ports {seg[1]}]
set_property PACKAGE_PIN D5 [get_ports {seg[0]}]
set_property PACKAGE_PIN D4 [get_ports {segg[7]}]
set_property PACKAGE_PIN E3 [get_ports {segg[6]}]
set_property PACKAGE_PIN D3 [get_ports {segg[5]}]
set_property PACKAGE_PIN F4 [get_ports {segg[4]}]
set_property PACKAGE_PIN F3 [get_ports {segg[3]}]
set_property PACKAGE_PIN E2 [get_ports {segg[2]}]
set_property PACKAGE_PIN D2 [get_ports {segg[1]}]
set_property PACKAGE_PIN H2 [get_ports {segg[0]}]
 
  set_property IOSTANDARD LVCMOS33 [get_ports {clk}] 
  
 set_property IOSTANDARD LVCMOS33 [get_ports {A[0]}] 
 set_property IOSTANDARD LVCMOS33 [get_ports {A[1]}] 
 set_property IOSTANDARD LVCMOS33 [get_ports {A[2]}] 
 set_property IOSTANDARD LVCMOS33 [get_ports {A[3]}]   
 set_property IOSTANDARD LVCMOS33 [get_ports {B[0]}]
 set_property IOSTANDARD LVCMOS33 [get_ports {B[1]}] 
 set_property IOSTANDARD LVCMOS33 [get_ports {B[2]}] 
 set_property IOSTANDARD LVCMOS33 [get_ports {B[3]}] 
 
set_property IOSTANDARD LVCMOS33 [get_ports an[7]]
set_property IOSTANDARD LVCMOS33 [get_ports an[6]]
set_property IOSTANDARD LVCMOS33 [get_ports an[5]]
set_property IOSTANDARD LVCMOS33 [get_ports an[4]]
set_property IOSTANDARD LVCMOS33 [get_ports an[3]]
set_property IOSTANDARD LVCMOS33 [get_ports an[2]]
set_property IOSTANDARD LVCMOS33 [get_ports an[1]]
set_property IOSTANDARD LVCMOS33 [get_ports an[0]]

set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {segg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {segg[0]}]

模拟仿真图像:

下载到开发板上的图片结果:

图一
图二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值