乘法器的两个乘数是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仿真结果如下: