移位加乘法器

思路,A,B相乘,A每个时钟周期左移,B每个时钟周期右移,用B0判断是否相加。

整个模块包括的端口信号:时钟、复位、载入数据A及载入信号LA,载入数据B及载入信号B,开始计算信号s,输出数据P,完成信号done。

数据流:(1)一个2n位宽的移位寄存器,用于A左移,一个n位宽的右移寄存器,用于B右移。

(由于进入状态S2后才会发出移位信号,移位是在状态S2之后,状态S2的第一个时钟周期会自动计算第一位的结果)

(2)将A左移后的结果和之前的结果相加得出结果,并且由此时的B0决定是否载入到寄存器中,若为1则载入新结果,否则保持原结果

(3)当计算完成后,判断出Bs为0,跳转到S3状态,发出done信号,再由done信号使P归零。

1 移位加乘法器顶层模块

`timescale 1ns/1ps

module ShiftProduct(Clk,Rst_n,A,B,s,P,Done,La,Lb);

input Clk,Rst_n;
input [7:0] A,B;
input s;
output Done;
output reg [15:0] P;

wire z;
wire [7:0] Bs;
wire [15:0] As;
input wire La,Lb;
wire Ea,Eb;
//wire Psel;
wire [15:0] Sum,DataP;
wire EP;

parameter S1=2'b00,S2=2'b01,S3=2'b10;
reg [1:0] state,next_state;

assign z= ~|Bs;
assign Ea = state==S2;
assign Eb = state==S2;
//assign Psel = state==S2; 
assign Done = state==S3;
assign EP= state==S2 &(Bs[0]) ;

always@(*) begin
case(state)
	S1: 
		if (s) next_state = S2;
		else next_state = S1;
	S2:	
		if(z) next_state = S3;
		else next_state =S2;
		
	S3:	
		if(s) next_state =S3;
		else next_state = S1;
		
	default: next_state = S1;
endcase
end

always@(posedge Clk ,negedge Rst_n) begin
state <= Rst_n?next_state:S1;
end

/*always@(*) begin
case(state)
	S1: Sum = 0;
	S2: if(Bs[0]) Sum = P + As;
	S3: Sum = As + P;
	default:Sum = 0;
endcase
end*/
assign Sum = P + As ; //虽然一直在计算得到sum,并且状态S2中,Psel一直为1,选通sum输入到datap,但是由于B0=0时,Ep=0,计算得到的sum传到datap后不会寄存到P寄存器。下一个周期,sum会重新计算,并且此时的P还是之前的P,此时的As再次更新。

assign DataP = Sum;// Psel?Sum:0;

always@(posedge Clk or negedge Rst_n) begin
if(~Rst_n)
	P <= 0;
else if(EP)
	P <= DataP;
else if(Done)
	P <= 0;
end

shiftlne shiftA(.Clk(Clk),.Data({{8'b0},A}),.La(La),.Ea(Ea),.w(1'b0),.A(As));
defparam shiftA.n = 16;

shiftrne shiftB(.Clk(Clk),.Data(B),.La(Lb),.Ea(Eb),.w(1'b0),.A(Bs));


endmodule





2 左移位和右移模块

`timescale 1ns/1ps 


module shiftlne (Clk,Data,A,La,Ea,w);

parameter n = 8;
input Clk,w;
input [n-1:0] Data;
output reg [n-1:0] A;
input La,Ea;

always@(posedge Clk ) begin 
if(La)
	A <= Data;
else if (Ea)
	A <= {A[14:0],w};
end


endmodule 
`timescale 1ns/1ps


module shiftrne(Clk,Data,La,Ea,A,w);
parameter n = 8;
input Clk,La,Ea,w;
input [n-1:0] Data;
output reg [n-1:0] A;

always @(posedge Clk) begin 
if(La)
	A <= Data;
else if (Ea)
	A <= {w,A[7:1]};
end




endmodule

3 测试模块

`timescale 1ns/1ps
`define clk_period 20

module tb_SP();

reg clk,rst_n,s,la,lb;
reg [7:0] a,b;
wire [15:0] p;
wire done;
ShiftProduct Sp0(.Clk(clk),.Rst_n(rst_n),.A(a),.B(b),.La(la),.Lb(lb),.s(s),.P(p),.Done(done));

initial clk = 1'b1;
always #(`clk_period /2) clk = ~clk;

initial begin 
rst_n = 0 ; la=0;
s = 0 ;
a = 8'd0; b=8'd0;
# (5*`clk_period/2) rst_n =1; 
# 20;a=8'b00000001;la=1;lb=1;b=8'b00000010;
#20;a=8'd0;b=8'b0;la=0;lb=0;
s=1;
#(8*`clk_period);
s=0;
#100;

# 20;a=8'b00011001;la=1;lb=1;b=8'b11000010;
#20;a=8'd0;b=8'b0;la=0;lb=0;
s=1;
#(8*`clk_period);
s=0;
#100;


# 20;a=8'b01100000;la=1;lb=1;b=8'b00000110;
#20;a=8'd0;b=8'b0;la=0;lb=0;
s=1;
#(8*`clk_period);
s=0;
#100;

end


initial
begin
  $fsdbDumpfile("ShiftP.fsdb");
  $fsdbDumpvars;
  $fsdbDumpon;
end

initial #5000 $finish;

endmodule

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值