忽略Verilog顺序和并行可能导致的延迟赋值错误

1、在always块与块之间是并行的,always块与initial块之间是并行的。
2、always块如果是用非阻塞(<=)是并行的;如果是用阻塞(=)是顺序的;

这道题最好的方法是用标准的状态机写法。

module gray( 
    input Clk,
    input Reset,
    input En,
    output reg[2:0] Output,
    output reg Overflow
);
reg [2:0] state;
reg flag;
initial begin
    state <= 3'b000;
    //flag <= 1'b0;
end
    always @(posedge Clk ) begin
        if(Reset) begin
				state <=3'b000;
            Output <= 3'b000;
            Overflow <= 1'b0;
        end
        else if(En) begin
            case(state)
                3'b000: begin
                    state <= 3'b001;
                    Output <= 3'b001;
                end
                3'b001: begin
                    state<=3'b011;
                    Output<=3'b011;
                end
                3'b011: begin
                    state<=3'b010;
                    Output<=3'b010;
                end
                3'b010:begin
                    state<=3'b110;
                    Output<=3'b110;
                end
                3'b110:begin
                    state<=3'b111;
                    Output<=3'b111;
                end
                3'b111:begin
                    state<=3'b101;
                    Output<=3'b101;
                end
                3'b101:begin
                    state<=3'b100;
                    Output<=3'b100;
                end
                3'b100:begin
                    state<=3'b000;
                    Output<=3'b000;
                    Overflow<=1'b1;
                end
            endcase
        end
    end
endmodule

也可以采取利用二进制数直接根据公式转为对应的格雷码,格雷码的最高位就是对应二进制的最高位,格雷码除了最高位的其他位都是对应二进制的这一位和上一位的异或,比如求二进制数110对应的格雷码,最高位和110一样是1,次高位是二进制数的次高位和最高位的异或(1^1=0),最低位是二进制数最低位和次高位的异或(1^0=1),所以格雷码是101。

展示一种错误的代码:

`timescale 1ns/1ps
//`timescale 1ns/1ps
module gray (
    input Clk,
    input Reset,
    input En,
    output  reg[2:0] Output,
    output  Overflow
);

  reg [2:0] normal;
  reg flow;

  always @(posedge Clk) begin
    if (Reset==1) begin
        normal<=0;
        flow <= 0;
    end
    else
    begin 
    if (normal == 7 && En==1) begin
        normal <= 0;
        flow <= 1;
    end
    else if (En==1 && normal !=7) begin
        normal <=normal+1;
    end
    else begin
         normal <= normal;
    end
    end
    output[2]<=normal[2];
    output[1]<=normal[2]^normal[1];
    output[0]<=normal[1]^normal[0];
    Overflow<=flow;
   
  end 
 
    
endmodule

错误原因,认为always里的赋值语句是顺序执行的,认为给output赋的值是在normal被更新完后进行的,而实际上output的赋值和normal的赋值时并行执行的,所以output的值利用的时上一轮的normal(output的值晚了一个周期)

正确写法:

`timescale 1ns/1ps
//`timescale 1ns/1ps
module gray (
    input Clk,
    input Reset,
    input En,
    output  [2:0] Output,
    output  Overflow
);

  reg [2:0] normal;
  reg flow;
  always @(posedge Clk) begin
    if (Reset==1) begin
        normal<=0;
        flow <= 0;
    end
    else
    begin 
    if (normal == 7 && En==1) begin
        normal <= 0;
        flow <= 1;
    end
    else if (En==1 && normal !=7) begin
        normal <=normal+1;
    end
    else begin
         normal <= normal;
    end
    end
   
  end 
  assign Output[2] = normal[2];
  assign Output[1] = normal[2] ^normal[1];
  assign Output[0] = normal[1]^normal[0];
  assign Overflow=flow;
    
endmodule

assign相当于导线,可以理解为只要normal改变,给output的赋值行为在瞬间进行。因此此时的output就是在和normal同步变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值