如何实现溢出代码?我不知道怎么了

时间:2019-05-30 04:58:50

标签: verilog fibonacci

如何实现溢出代码?

我不知道怎么了。结果中间是负数。下面是代码段

module fibonacci(input clk, input rst, output [7:0]out, output reg overflow);

reg [7:0]a,b;

always@(posedge rst)
begin
    a =8'b0;
    b =8'b1;
end
always@(posedge clk)
begin
    if ( a < 8'b11111111 ) begin
        b = a + b ;
        a = b - a ;

    end

    else begin

    overflow = 1'b1;   //is that wrong??

    end
end

assign out = a ;

endmodule

和此处的测试平台代码

initial begin

rst = 1;
clk =0;

#0.5
rst = 0;
end

always begin
#1 
clk = !clk;
end

fibonacci fib(clk,rst,out,overflow);
endmodule

enter image description here

让我知道怎么了

1 个答案:

答案 0 :(得分:1)

此负数的原因是该数字在two's complement representation中进行了解释。在89之后,您期望的实际数字是144,它是二进制的10010000。但是,在二进制补码表示中,最重要的位是数字的符号。 “ 1”表示该数字应为负数,可以通过以下方式计算:

~10010000 + 1 = 01101111 + 1 = 01110000 = (-)112

顺便提一下,您发布的代码还有其他一些问题。首先让我回答这个问题:

  

溢出= 1'b1; //是错了吗?

不是这一行,但是处理overflow的方式并不完全正确。在您的代码中,overflow只能成为x1。永远不会是0。您应该在条件块的第一部分和重置部分中将overflow分配给0

第二件事是您应该在Verilog中使用non-blocking assignments来创建顺序逻辑。在代码中,您正在使用阻塞分配,这意味着您首先更新b,然后使用已经更新的值a更新b。如果需要使用阻止分配,则应创建一个combinational block

此外,您应该组合时钟敏感部分和复位敏感部分,以使aboverflow都被同一always块修改。

所有这些建议将大致翻译为:

always @(*)
begin
    b_next = a + b;
    a_next = b_next - a;
end 

always @(posedge clk or negedge rst)
begin
    if (~rst) begin
        a <= 8'b0;
        b <= 8'b1;
        overflow <= 1'b0;
    end
    else if (a < 8'b11111111) begin
        b <= b_next;
        a <= a_next;
        overflow <= 1'b0    
    end
    else begin
        overflow <= 1'b1;
    end
end

如您所见,我还将重设转换为异步,低电平有效的重设。尽管这不是强制性的,但很常见。复位信号旨在将所有触发器保持在复位状态,即使设备的电源缓慢上升也是如此。如果复位信号为高电平有效,则信号本身可能会缓慢上升。