基于FPGA的“乘法器”设计

该文描述了一个基于Verilog的二进制乘法器设计,包括状态机和数据通道两部分。乘法器处理4位2进制数的乘法,使用加法和移位结合的算法。状态机控制乘法运算流程,数据通道执行实际的计算操作,如移位、加载和加法。测试平台验证了针对特定输入的正确性。
摘要由CSDN通过智能技术生成

乘法器的两个乘数是4位2进制数,输入乘积项是8位位宽的2进制数。当乘数准备好后,START信号有效,电路开始进行乘法运算,当乘法运算结束后,电路输出DONE有效信号。另一个控制信号是RESET信号,用来完成复位时使用。乘法电路采用的算法要求使用加法和移位相结合的算法来实现电路。
1.二进制乘法介绍
二进制数乘法过程可仿照十进制数乘法进行。二进制数乘法的法则为:0×0=0,0×1=1×0=0,1X1=1例如:0101和1100相乘的过程如图所示:

根据流程图进行有限状态机和数据通道设计:

状态机部分代码:

module state_machine(clk,reset,clr,Shift,start,
LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,eql_4,Q_lsb);
input clk,reset,eql_4,start,Q_lsb;
output Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr;
reg Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr;
reg[2:0] present_state,next_state;
parameter idle=3'b000,init=3'b001,add=3'b010,shift=3'b011,done=3'b100,empty=3'b101;
always@(posedge clk or negedge reset)
    if(1'b0==reset)
  present_state<=idle;
  else
  present_state<=next_state;
always@(present_state,eql_4,Q_lsb,start)
    case(present_state)
  idle:
   begin
   if(1'b1==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)
   next_state<=add;
   else
   next_state<=shift;
  {Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr}=8'b00110001;
  end
  
  add:
  begin
  next_state<=shift;
  {Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr}=8'b01001001;
  end
  
  
  
  shift:
  begin
  if(1'b1==eql_4)
  next_state<=done;
  else if(1'b1==Q_lsb)
  next_state<=add;
  else
  next_state<=shift;
  {Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr}=8'b10000101;
  end
  
  done:
  begin
  next_state<=empty;
  {Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr}=8'b00000011;//??
  end
  
  empty:
  begin
  next_state<=idle;
  {Shift,LD_P,LD_Q,LD_R,LD_G,cnt_en,Done,clr}=8'b00000011;
  end
  
  endcase
endmodule


 

数据通道:

module datapath(

clock,
reset_n,

r_in_Q,
LD_Q,
shift,
Q_LSB,

cnt_en,
eq_4,

r_in_R,
LD_R,

LD_G,

LD_P,
P_high,
P_low

);

input clock;  
input reset_n;
input [3:0]r_in_Q;
input LD_Q;
input shift;
output Q_LSB;

input cnt_en;
output eq_4;

input [3:0]r_in_R;
input LD_R;

input LD_G;

input LD_P;
output [3:0]P_high;
output [3:0]P_low;

wire [3:0] R_and_P;
wire [3:0] R_to_add;
wire P_high_LSB;
wire g_out;
wire cout;

s_reg Q(
.clk  (clock),
.LD   (LD_Q),
.shift(shift),
.r_in (r_in_Q),
.r_lsb(Q_LSB),
.reset_n(reset_n),
.s_reg(),
.shift_in_data(1'b0)
);

s_reg R(
.clk  (clock),
.LD   (LD_R),
.shift(1'b0),
.r_in (r_in_R),
.reset_n(reset_n),
.r_lsb(),
.s_reg(R_to_add),
.shift_in_data()
);

s_reg P_h(
.clk  (clock),
.LD   (LD_P),
.shift(shift),
.r_in (R_and_P),
.r_lsb(P_high_LSB),
.reset_n(reset_n),
.s_reg(P_high),
.shift_in_data(g_out)
);

s_reg P_l(
.clk  (clock),
.LD   (1'b0),
.shift(shift),
.r_in (4'b0),
.r_lsb(),
.reset_n(reset_n),
.s_reg(P_low),
.shift_in_data(P_high_LSB)
);

G_reg G_reg(
.clk(clock),
.ld_g(LD_G),
.G_in(cout),
.G_out(g_out),
.reset_n(reset_n)

);

Counter count(
  .clk(clock),
  .clr_n(reset_n),
  .LD(1'b0),
  .EN(cnt_en),
  .UD(1'b1),
  .pre_value(),
  .cnt_value(),
  .eq_4(eq_4)

);

adder adder(
.R(R_to_add),
.P(P_high),
.cin(1'b0),
.sum(R_and_P),
.cout(cout)
);

endmodule 

顶层封装:

module Mul( clock,reset_n,en,Q,R,P,done);
 
 input en;
 input clock,reset_n;
 input [3:0] Q,R;
 output done;
 output [7:0]P;

wire clr,shift,cnt_en,LD_R,LD_P,LD_Q,LD_G,eql_4,Q_lsb;
 
datapath datapath(

.clock(clock),
.reset_n(clr),

.r_in_Q(Q),
.LD_Q(LD_Q),
.shift(shift),
.Q_LSB(Q_lsb),

.cnt_en(cnt_en),
.eq_4(eql_4),

.r_in_R(R),
.LD_R(LD_R),

.LD_G(LD_G),

.LD_P(LD_P),
.P_high(P[7:4]),
.P_low(P[3:0])

);
 
 
 
state_machine state_machine(
 .clk(clock),
 .reset(reset_n),
 .clr(clr),
 .Shift(shift),
 .start(en),
 .LD_P(LD_P),
 .LD_Q(LD_Q),
 .LD_R(LD_R),
 .LD_G(LD_G),
 .cnt_en(cnt_en),
 .Done(done),
 .eql_4(eql_4),
 .Q_lsb(Q_lsb)
 );
 
endmodule



 

计数器:

module Counter
(
  clk,
  clr_n,
  LD,
  EN,
  UD,
  pre_value,
  cnt_value,
  eq_4


);

input clk;
input clr_n;
input LD;
input EN;
input UD;
input [3:0] pre_value;
output[2:0] cnt_value;
output eq_4;

reg [2:0] cnt_value;
reg eq_4;

always @(posedge clk or negedge clr_n) begin

    if(!clr_n) begin
    cnt_value <= 3'b000;
    end
    else if(LD) begin
    cnt_value <= pre_value;
    end
    else if(EN) 
   begin
        if(UD) 
                begin         
                cnt_value <= cnt_value + 1;               
            end
        
        else begin
        cnt_value <= cnt_value - 1;
        end
   end
    else begin
    cnt_value <= cnt_value;
    end

end

always@(cnt_value)
begin
   if (cnt_value==3'b100)
    eq_4=1'b1;
  else
  eq_4=1'b0;
end
endmodule

移位寄存器:

module s_reg(clk,LD,shift,r_in,r_lsb,reset_n,shift_in_data,s_reg);
input clk,LD,shift,reset_n,shift_in_data;
input[3:0]r_in;
output r_lsb;
output [3:0]s_reg;

reg[3:0]s_reg;

always@(posedge clk or negedge reset_n)
begin
if(!reset_n)
    begin
    s_reg<=4'b0000;
    end
    else if(1'b1==LD)
    begin
        s_reg<=r_in;
    end
            else if(1'b1==shift)
            begin
            s_reg<={shift_in_data,s_reg[3:1]};
            end
                else
                    begin    
                    s_reg<=s_reg;
                    end
end
assign r_lsb=s_reg[0];

endmodule

一位寄存器:

module G_reg(
clk,
ld_g,
G_in,
G_out,
reset_n

);
input clk,ld_g,G_in,reset_n;
output G_out;
reg G_out;


always@(posedge clk or negedge reset_n)
if(!reset_n)
  begin
  G_out<=1'b0;
  end
  else if(1'b1==ld_g)
   begin
      G_out<=G_in;
	end
		else begin
		G_out<=G_out;
		end


endmodule
		

四位全加器:

module adder(R,P,cin,sum,cout);
input [3:0] R;
input [3:0] P;
input     cin;
output [3:0]sum;
output     cout;

assign{cout,sum}=R+P+cin;
	
endmodule

TestBench:

module Mul_tb();

reg clock;
reg reset_n;
reg en;
reg [3:0]Q;
reg [3:0]R;
wire [7:0]P;
wire done;



Mul uut( 
.clock(clock),
.reset_n(reset_n),
.en(en),
.Q(Q),
.R(R),
.P(P),
.done(done)
);



always 
	#25 clock=~clock;
	
initial begin
	

  clock=1'b0;
  en=1'b1;
  reset_n=1'b0;
  
  
 #50
 Q=4'b0010;
 R=4'b0011;
 #70
 reset_n=1'b1;
 #50
 en=1'b1;
 #50
 en=1'b0;
 
 #500
 Q=4'b0100;
 R=4'b1111;
 #50
 reset_n=1'b0;
 #50
 reset_n=1'b1;
 #50
 en=1'b1;
  #50
 en=1'b0;

 #500
 Q=4'b1111;
 R=4'b1111;
 #50
 reset_n=1'b0;
 #50
 reset_n=1'b1;
 #50
 en=1'b1;
  #50
 en=1'b0;

 #500

 $display("sim end!!!"); 
 $stop;
end     
endmodule

 测试平台仅对0010*0011、0100*1111、1111*1111进行了测试,ModelSim仿真结果如下:

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

保佑我不掉头发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值