基于Verilog的四位乘法器设计

1.二进制乘法介绍

        二进制数乘法过程可仿照十进制数乘法进行。但由于二进制数只有 0或1两种可能的乘数位,导致二进制乘法更为简单。二进制数乘法的法则为:0X0=0,01=1X0=0,1X1=1。

       由低位到高位,用乘数的每一位去乘被乘数,若乘数的某一位为 1,则该次部分积为被乘数;若乘数的某一位为 0,则该次部分积为 0。某次部分积的最低位必须和本位乘数对齐,所有部分积相加的结果则为相乘得到的乘积。

2.流程图设计:

       根据上述算法,首先设计出二进制乘法流程图,如图 4.所示,流程图中第一个是 idle 步骤,在该步骤中电路不做任何工作,等待乘数和被乘数的输入以及 START 信号的输人。在检测到 START 信号有效后,电路进入到初始化状态,在该状态下对 P乘积项、G 进位端和 C计数器进行清零操作。

然后电路判断 Qlsb即Q存器的最低有效位是否为1,如果是1就完成P的高 4 位和R寄存器的加操作,进位位是 G。如果 Qlsb 为 0,就跳过加法运算,直接进入到移位的操作。P和R相加以后,下一步直接跳到移位操作在移位的步骤中,完成对 P和Q的右移操作,同时完成 C计数器加 1的操作。

        移位步骤过后,来判断 C是否等于3,如果等于3就直接进入到 done 步骤,乘法计算过程结束。否则再次进入到判断 Q_lsb 步骤,接下来的步骤如上所述在流程图中要完成4次移位操作,因此C最终的结果应当是 4,这里判断是否等于 3 是考虑到电路在实现的过程中加1的结果需要下一周期才会出现,在当前的时钟周期里判断,只能来判断结果是否等于 4。

3.数据通道设计:

        数据通道来源于流程图的解读,下面来对流程图进行分解。在流程图中可以看到需要R寄存器,该寄存器来存储被乘数。需要 Q移动寄存器,该寄存器能够进行右移操作,能保存数据;电路中需要乘积项寄存器 P,P 能够实现右移功能,能够实现数据保存功能。

        需要G进位寄存器,该寄存器也能实现右移功能。在加法运算的时候需要加法器,加法器完成P的高4位和R 被乘数的加法,加法的结果保存在 P 寄存器中,进位位保存在 G 寄存器中。在计数过程中需要计数器,计数器每完成一次移位的操作就要计数一次。具体的数据通道如图 4.7所示。

//DataPath整体数据通道
module datapath(
    clk,clr,shift,cnt_en,ld_P,ld_R,
    ld_Q,ld_g,R,Q,P,eq_3,Q_lsb,
    P_H_OUT,P_L_OUT,ge,shi,bai,R_shi,Q_shi,R_ge,Q_ge
    );
input clk,clr,shift,cnt_en,ld_P,ld_R,ld_Q,ld_g;
input [3:0] R,Q;
output [7:0] P;
output [3:0] P_H_OUT,P_L_OUT,ge,shi,bai,R_shi,Q_shi,R_ge,Q_ge;
output eq_3;
output Q_lsb;
wire [3:0]R_to_add;//R寄存器输出
wire [3:0]R_and_P;//R与P的和
wire cout;//加法器进位输出
wire G_to_P;//G寄存器输出
wire [3:0]P_H_OUT;//P寄存器高位输出
wire P_H_lsb;//P寄存器高位的最低位
wire [3:0] CQ,CR;
//实例化比较器模块
comparator comp(.a(R),.b(Q),.CR(CR),.CQ(CQ));

//实例化移位寄存器
shift_reg Qreg(
.clk(clk),
.reset(clr),
.shift(shift),
.load(ld_Q),
.in_data(CQ),
.shift_in_data(1'b0),
.shift_reg(),
.shift_reg_lsb(Q_lsb)
);
//实例化移位寄存器
shift_reg Rreg(
.clk(clk),
.reset(clr),
.shift(1'b0),
.load(ld_R),
.in_data(CR),
.shift_in_data(1'b0),
.shift_reg(R_to_add),
.shift_reg_lsb()
);

//实例化移位寄存器
shift_reg P_Hreg(
.clk(clk),
.reset(clr),
.shift(shift),
.load(ld_P),
.in_data(R_and_P),
.shift_in_data(G_to_P),
.shift_reg(P_H_OUT),
.shift_reg_lsb(P_H_lsb)
);

//实例化移位寄存器
shift_reg P_L(
.clk(clk),
.reset(clr),
.shift(shift),
.load(1'b0),
.in_data(4'b0),
.shift_in_data(P_H_lsb),
.shift_reg(P_L_OUT),
.shift_reg_lsb()
);
//实例化C计数器
counter counter(
.clk(clk),
.clr(clr),
.cnt_en(cnt_en),
.eq_3(eq_3)
);
//实例化加法器
adder adder(
.a(R_to_add),
.b(P_H_OUT),
.c(cout),
.sum(R_and_P)
);
//实例化G寄存器
G_reg G_reg(
    .clk(clk),
    .ld_g(ld_g),
    .din(cout),
    .dout(G_to_P),
    .clr(clr)
);
assign P = {P_H_OUT,P_L_OUT};
//实例化个十百转换模块
Multiplier_out Multiplier_out(
    .sumin(P),
    .ge(ge),
    .shi(shi),
    .bai(bai)
);
//实例化个十百转换模块
Multiplier_out R_out(
    .sumin(R),
    .ge(R_ge),
    .shi(R_shi),
    .bai()
);
//实例化个十百转换模块
Multiplier_out Q_out(
    .sumin(Q),
    .ge(Q_ge),
    .shi(Q_shi),
    .bai()
);

endmodule

4.状态机设计:

       状态机如图所示,状态机按照流程图画出,流程图中每个动作对应着一个状态,因此需要 5 个状态。下面分别对每个状态进行说明,idle 是空闲状态,无论电路处于何种状态,当reset 信号有效时,电路必须进入到idle状态。idle状态在 start信号有效时下一状态进入到 init 状态,否则下一状态还在 idle 状态等待。在init 状态下,如果输人信号 Q_Isb 是1的情况下,下一状态会进入到 add 状态,否则下一状态进入到 shift 状态。add 状态的下-状态直接进入到 shift 状态。在 shift 状态下,如果 egl_3 信号为 1,则下一状态进入到 done状态,否则看 Q_lsb 信号是否有效,如果eql_3信号为0且Q_lsh信号为1的情况下,shift状态的下一个状态进入到add 状态。如果eql_3 信号为0且Q_lsb信号为0的情况下,shift状态的下一个状态进入到 shift 状态。done状态的下一个状态还是 done,直到电路reset信号有效的情况下回到 idle状态。

//状态机
module state_machine(clk,reset,clr,shift,ld_P,ld_R,ld_Q,ld_g,eq_3,Q_lsb,START,DONE,cnt_en,present_state,next_state);
input clk,reset,eq_3,START,Q_lsb;
output shift,ld_P,ld_R,ld_Q,ld_g,DONE,clr,cnt_en,present_state,next_state;
reg shift,ld_P,ld_R,ld_Q,ld_g,DONE,clr,cnt_en;
reg [2:0]c;//present_state为当前状态,next_state为下一个状态
reg [2:0]present_state,next_state;
parameter idle=3'b000;//空闲状态
parameter init=3'b001;//初始化状态
parameter add=3'b010;//加法状态
parameter Shift=3'b011;//移位状态
parameter done=3'b100;//完成状态
parameter empty=3'b101;//延时状态
always@(posedge clk,negedge reset)
if(1'b0==reset)//reset为低电平时,状态机回到空闲状态
    present_state<=idle;
else
    present_state<=next_state;//否则状态机进入下一个状态
always@(present_state,eq_3,START,Q_lsb)
case(present_state)
idle:begin if(1'b0==START)//当START按下时
    next_state=init;
    else
    next_state=idle;//否则状态机仍然处于空闲状态
    {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00000000;//状态机的输出
end
init:begin if(1'b1==Q_lsb)//当Q_lsb为高电平时,状态机进入加法状态
    next_state=add;
    else
    next_state=empty;//否则状态机仍然处于初始化状态
    {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00110001;//状态机的输出
end
add:begin
    next_state=empty;//状态机进入移位状态
    {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b01001001;//状态机的输出
    end
Shift:begin
    if(1'b1==eq_3)//当eq_3为高电平时,状态机进入完成状态
        next_state=done;
        else
        if(!eq_3&&Q_lsb)
            next_state=add;//否则状态机仍然处于移位状态
            else
            next_state=Shift;//否则状态机仍然处于移位状态
            {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b10001101;//初始化状态机的输出
    end
empty:begin
    {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00000001;//状态机的输出
    next_state=Shift;//否则状态机进入完成状态*/
end
done:begin
	/*
    next_state<=done;//状态机进入延时状态
    {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00000011;//状态机的输出
	*/ 
	  {shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00000011;//状态机的输出
	
	 if(1'b0==START)begin//当START按下时
     next_state=idle;
	  //{shift,ld_P,ld_Q,ld_R,ld_g,cnt_en,DONE,clr}=8'b00000000;//状态机的输出
	  end
    else begin
    next_state=done;//保持当前状态
    end

end
  default: next_state=idle;
endcase
endmodule

5.顶层设计:

//顶层设计
module Multiplier(
    START,done,clk,reset,Q,
    R,P,present_state,next_state,
    eq_3,Q_lsb,P_H_OUT,
    P_L_OUT,shift,ge,shi,bai,
    data_ge,data_shi,data_bai,
	 R_shi,Q_shi,R_ge,Q_ge,
	 data_Q_shi,data_R_ge,data_R_shi,data_Q_ge
    );
input START,clk,reset;
input [3:0] R,Q;
output [7:0] P;
output [3:0] P_H_OUT,P_L_OUT,ge,shi,bai,R_shi,Q_shi,R_ge,Q_ge;
output [2:0] present_state,next_state;
output done,eq_3,Q_lsb,shift;
wire done;
wire shift,ld_P,ld_R,ld_Q,ld_g,clr,cnt_en,eq_3,Q_lsb;
wire [7:0] P;
wire [3:0] P_H_OUT,P_L_OUT;
output [6:0] data_ge,data_shi,data_bai,data_Q_ge,data_Q_shi,data_R_ge,data_R_shi;
wire [6:0] data_ge,data_shi,data_bai,data_Q_ge,data_Q_shi,data_R_ge,data_R_shi;
//实例化状态机
state_machine state_machine(.clk(clk),.reset(reset),.cnt_en(cnt_en),
.clr(clr),.shift(shift),.ld_P(ld_P),.ld_R(ld_R),.ld_Q(ld_Q),.ld_g(ld_g),
.eq_3(eq_3),.Q_lsb(Q_lsb),.START(START),.DONE(done),
.present_state(present_state),.next_state(next_state));
//实例化数据通路
datapath datapath(
.clk(clk),.clr(clr),.shift(shift),
.cnt_en(cnt_en),.ld_P(ld_P),.ld_R(ld_R),
.ld_Q(ld_Q),.ld_g(ld_g),.R(R),.Q(Q),
.P(P),.eq_3(eq_3),.Q_lsb(Q_lsb),
.P_H_OUT(P_H_OUT),.P_L_OUT(P_L_OUT),
.ge(ge),.shi(shi),.bai(bai),.R_ge(R_ge),
.R_shi(R_shi),.Q_ge(Q_ge),.Q_shi(Q_shi)
);
//实例化数码管模块
 seven_seg out_ge(
   .num1(ge),
   .data1(data_ge)
);
//实例化数码管模块
 seven_seg out_shi(
   .num1(shi),
   .data1(data_shi)
);
//实例化数码管模块
 seven_seg out_bai(
   .num1(bai),
   .data1(data_bai)
);
//实例化数码管模块
 seven_seg out_R_ge(
   .num1(R_ge),
   .data1(data_R_ge)
);
//实例化数码管模块
 seven_seg out_R_shi(
   .num1(R_shi),
   .data1(data_R_shi)
);
//实例化数码管模块
 seven_seg out_Q_ge(
   .num1(Q_ge),
   .data1(data_Q_ge)
);
//实例化数码管模块
 seven_seg out_Q_shi(
   .num1(Q_shi),
   .data1(data_Q_shi)
);
endmodule

6.移位寄存器模块

//移位寄存器(通用)
module shift_reg(clk,reset,in_data,shift,load,shift_reg_lsb,shift_in_data,shift_reg);
input clk,reset,shift,load;
input [3:0] in_data;
input shift_in_data;
output shift_reg_lsb;
output [3:0] shift_reg;
reg [3:0] shift_reg;
always @(posedge clk,negedge reset)
    if(1'b0===reset)//reset为低电平时,寄存器清零
        shift_reg<=4'b0;
    else if(1'b1===load)//load为高电平时,将in_data赋值给shift_reg
        shift_reg<=in_data;
    else if(1'b1===shift)//shift为高电平时,将shift_reg左移一位
        shift_reg<={shift_in_data,shift_reg[3:1]};
    else
        shift_reg<=shift_reg;//否则shift_reg不变
assign shift_reg_lsb=shift_reg[0];//shift_reg_lsb为shift_reg的最低位
endmodule

//C计数器
module counter(clk,clr,cnt_en,eq_3);
input clk,clr,cnt_en;
output eq_3;
reg eq_3;
reg [2:0] cnt_reg;
always@(posedge clk,negedge clr)
if(1'b0==clr)//clr为低电平时,计数器清零
    cnt_reg<=3'b0;
else if(1'b1==cnt_en)//cnt_en为高电平时,计数器加一
    cnt_reg<=cnt_reg+1'b1;
    else
    cnt_reg<=cnt_reg;//否则计数器不变
always@(cnt_reg)
if(3'b100==cnt_reg)//当计数器为3时,eq_3为高电平
    eq_3=1'b1;
else
    eq_3=1'b0;//否则eq_3为低电平
endmodule

7.加法器模块

//加法器
module adder(a,b,c,sum);
input [3:0] a,b;
output [3:0] sum;
output c;
reg [3:0] sum;
reg c;
always@(a,b)
{c,sum}=a+b;
endmodule

8.G寄存器模块

//G寄存器
module G_reg(clk,ld_g,din,dout,clr);
input clk,ld_g,din,clr;
output dout;
reg dout;
always@(posedge clk)
if(clr==1'b0)//clr为低电平时,G寄存器清零
    dout<=1'b0;
else if(ld_g)//ld_g为高电平时,将din赋值给dout
    dout<=din;
else
    dout<=dout;//否则dout不变
endmodule

9.其他模块

//七段数码管模块
module seven_seg(num1,data1);
input [3:0]num1;
output [6:0]data1;
reg [6:0]data1;
always@(num1) begin
case (num1)
      4'd0: begin data1 = 7'b1000000;  end
		4'd1: begin data1 = 7'b1111001; end
		4'd2: begin data1= 7'b0100100; end
		4'd3: begin data1 = 7'b0110000; end
		4'd4: begin data1 = 7'b0011001;  end
		4'd5: begin data1 = 7'b0010010;  end
		4'd6: begin data1 = 7'b0000010;  end
		4'd7: begin data1 = 7'b1111000; end
		4'd8: begin data1 = 7'b0000000;  end
		4'd9: begin data1 = 7'b0010000; end
      default: begin data1 = 7'b0000001; end
endcase
end
endmodule

//数位转换模块
module Multiplier_out(
    sumin,//乘法器输出
    ge,//个位
    shi,//十位
    bai,//百位
);
input [7:0]sumin;
output [3:0]ge,shi,bai;
reg [3:0]ge,shi,bai;
always@(sumin) begin
    bai=sumin/100;//百位
    shi=(sumin-bai*100)/10;//十位
    ge=sumin-bai*100-shi*10;//个位
end
endmodule

//比较转换器模块
module comparator(
    a,b,//比较数
    CQ,CR
);
input [3:0]a,b;
output [3:0]CQ,CR;
reg [3:0]CQ,CR,TMP;
always@(a,b) begin
    if(a>b) begin
	 CR<=b;
	 CQ<=a;
		  end
    else
	     begin
        CR<=a;
        CQ<=b;
		  end
end
endmodule

  • 13
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值