其他分享
首页 > 其他分享> > 除法器设计

除法器设计

作者:互联网

除法器的设计思路比较复杂,主要是移位,相除,将除数和被除数分别放在寄存器B,A,然后,增加一个同样位宽n的移位寄存器R,R中8‘b0作为高位,A中数据作为低位,运算过程需要2n个时钟周期,过程是这样的。

(1)第一个周期进行载入数据A;并且给出计数器减1信号,下一个周期计数器减1,表示已经进行第一次移位。

(2)第二个周期将数据将A中数据最高位移入R;并进行两个判断:判断此时R是否大于等于B,如果大于,则选通R-B,并给出载入LR信号,在下一个周期载入LR,如果R小于B,那么则没有LR信号,并且在下一个周期给出ER信号,在下下一个周期使其移位,再次比较;判断此时计算是否完成,完成的标志是计数器归零,若归零,跳转到完成状态,若没有,进入第三个时钟周期,再次移位...

(3)第三个周期,对A进行移位;给出计数器减1信号;

(4)第四个周期,将A[7]移入R中,并进行判断,判断此时R是否大于等于B,判断此时计算是否结束...

一直进行2n个时钟周期,此时计数器归零,得到商和余数。

1、除法器顶层模块

顶层端口信号:时钟、复位、载入数据信号LA,EB,计算触发信号s,数据A、B,输出商Q,余数R,完成信号Done。

有一些犯错的地方:

(1)最开始写代码时,在从S1进入状态S2后,对A进行了移位,再对R进行的移位,这样的过程漏掉了A的最高位。因此必须严格按照先载入数据后,一定要先让ER有效,移入寄存器R后的下一个周期才让A移位。【进入S2后立即给出了移位信号,但是上一个状态是S1且S3有效,给出了A的移位,因此这个周期中A的最高位实际上是初始的A[6]】

assign EA = (state==S1&s)|(state==S3);
assign ER = state==S2;

(2)计数器的置位为7还是8是有区别的。如果置位为7,进入S2后,就应该立刻进行第一次移位到RA中。此时在S1中由于s=1给出的信号是EA、ER都有效,ER有效保证移入最高位数据,EA有效保证下一个周期时,已经移位,而不会少移位一次。考虑不给出EA有效的情况,由于ER连续两个周期有效,(S1&s 和S2),连续进行两次移位,但是EA最开始并不有效,因此A=11000110会保持两个周期,会连续两个周期读入最高位。因此这种情况下,EA也应该有效,保证第二次移位时,移入的数据是A[6](因为置位为7,并且是一旦进入周期S3,计数-1,计数-1意味着已经移位1次,0=7-7,意味着移位了7次,而最开始state==S1&s时移位一次(处于状态S2),因此R移位8次,即将跳出循环。计数器7到0是对的)

错误情况:

assign EA = (state==S3);//|(state==S1&s);
assign ER = (state==S2)|(state==S1&s);

正确情况
 

assign EA = (state==S3)|(state==S1&s);
assign ER = (state==S2)|(state==S1&s);

如果计数器置位为8,那么应该是如下代码。

assign EA = (state==S3);
assign ER = (state==S2);

(3)关于移位寄存器A,应该在每个状态S2周期都会移位,无论上一个周期S3中是否满足cout=1。

错误情况

assign EA = (state==S3)&cout;

正确情况

assign EA = (state==S3);

(4)R和Q数据复位,由done决定,done决定Q的复位,只要done完成,则复位。(done连接到该寄存器的La载入控制信号),R复位复杂一点,Rsel和LR控制选择信号和载入,载入有效可以是状态S1下且s=0时,或需要载入R-B时(S3下且cout=1),Rsel只有在S3下且cout为1时才载入计算结果R-B。

`timescale 1ns/1ps

module Division(Clk,LA,EB,s,R,Q,DataA,DataB,Rst_n,Done);

parameter n = 8;
input Clk,Rst_n,s,LA,EB;
input [n-1:0] DataA,DataB;
input Done;
output wire [n-1:0] R,Q;

parameter S1=2'b00,S2=2'b01,S3=2'b10,S4=2'b11;
reg [1:0] state,next_state;
reg [2:0] cnt;
wire EC;
wire [n-1:0] A;
wire LR,ER,Rsel;
wire [n:0] sum;
wire [n-1:0] adder_a,adder_b;
wire cout;
wire EQ;
reg [n-1:0] B;

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

always@(posedge Clk ,negedge Rst_n) begin
if(~Rst_n)
	state <= S1;
else
	state <= next_state;
end



always@(posedge Clk ,negedge Rst_n ) begin
if(~Rst_n)
	cnt <= 3'd7;
else if (EC)
	cnt <= cnt - 1'b1;
else if (Done)
	cnt <= 3'd7;
end

assign EC = state==S2;
wire [7:0] datax;
assign datax = Rsel?sum[n-1:0]:8'd0;
shiftlne shiftA(.Clk(Clk),.w(1'b0),.La(LA),.A(A),.Data(DataA),.Ea(EA));
shiftlne shiftRA(.Clk(Clk),.w(A[7]),.La(LR),.Ea(ER),.Data(datax),.A(adder_a));

//Adder adder0(.Cin(1'b1),.Cout(cout),.A(adder_a),.B(adder_b),.Sum(sum));
shiftlne shiftQ(.Clk(Clk),.La(~Rst_n|Done),.Ea(EQ),.Data(8'd0),.w(cout),.A(Q));

always@(posedge Clk,negedge Rst_n) begin
if(~Rst_n) 
	B <= 0;
else if(EB)
	B <= DataB;
end

assign adder_b = ~B;
assign EA = (state==S1&s)|(state==S3);
assign ER = (state==S1&s)|state==S2;
assign LR = ((state==S1)&(s==0))|((state==S3)&cout);
assign EQ = state==S3;
assign sum = {1'b0,adder_a}+{1'b0,adder_b}+1'b1;
assign R = adder_a;
assign cout = sum[n];
assign Done = state==S4;
assign Rsel = (state==S3)&(cout); 

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 

3、测试代码

`timescale 1ns/1ps
`define clk_period 20

module tb_Div();

reg clk,rst_n,s,la,lb;
reg [7:0] a,b;
//#wire [15:0] p;
wire done;

wire [7:0] q,r;

Division Div0(.Clk(clk),.Rst_n(rst_n),.DataA(a),.DataB(b),.LA(la),.EB(lb),.s(s),.Q(q),.R(r),.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'd200;la=1;lb=1;b=8'd20;
#20;a=8'd0;b=8'b0;la=0;lb=0;
s=1;
#(18*`clk_period);
s=0;
#100;

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


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


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


end


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

initial #5000 $finish;

endmodule

标签:除法器,clk,S3,S2,S1,state,设计,移位
来源: https://blog.csdn.net/baidu_38971369/article/details/123126568