除法器设计
作者:互联网
除法器的设计思路比较复杂,主要是移位,相除,将除数和被除数分别放在寄存器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