【问题标题】:Verilog Synthesis fails on if statement containing two variablesVerilog 综合在包含两个变量的 if 语句上失败
【发布时间】:2013-06-05 18:29:34
【问题描述】:

我遇到了一个综合问题,如果我在 if 语句中有两个变量,综合将失败(带有非常误导和无益的错误消息)。

给定下面的代码sn-p

case(state)
//other states here
GET_PAYLOAD_DATA:
        begin
                if (packet_size < payload_length) begin
                    packet_size <= packet_size + 1;
                    //Code to place byte into ram that only triggers with a toggle flag
                    next_state = GET_PAYLOAD_DATA;
                end else begin
                    next_state = GET_CHKSUM2;
                end
end

在综合过程中,Xilinx ISE 出现错误:

 ERROR:Xst:2001 - Width mismatch detected on comparator next_state_cmp_lt0000/ALB. Operand     A and B do not have the same size.

该错误声称 next_state 不正确,但如果我取出 payload_length 并为其分配一个静态值,它就可以正常工作。由于 packet_size 和 payload_length 都是整数类型,它们的大小相同,这不是问题。因此,我认为它与无法在硬件中实现的 for 循环类似的问题,除非它是具有定义结束的静态循环。但是 If 语句应该可以工作,因为它只是 2 个二进制值之间的比较器。

我在这里尝试做的是,当我的模块接收到一个字节时,它将被添加到 RAM 中,直到达到整个有效负载(我从早期的数据包数据中获得)的大小,然后更改为处理校验和的不同状态。由于数据一次只输入 1 个字节,我多次回忆这个状态,直到计数器达到限制,然后我将下一个状态设置为其他状态。

然后我的问题是,如何在调用我的状态并重复直到计数器达到有效负载的长度而不出现错误的情况下获得相同的结果?

编辑: 根据 cmets 的要求,如何声明 packet_size 和 payload_length 的片段

integer payload_length, packet_size;

initial begin
    //other stuff
    packet_size <= 0;
end

always @ (posedge clk) begin
    //case statements with various states
    GET_PAYLOAD_LEN:
        begin
            if (rx_toggle == 1) begin
                packet_size <= packet_size + 1;
                addr <= 3;
                din <= rx_byte_buffer;
                payload_length <= rx_byte_buffer;
                next_state = GET_PAYLOAD_DATA;
            end else begin
                next_state = GET_PAYLOAD_LEN;
            end
        end

rx_byte_buffer 是我的模块接收的 8 位宽输入数据的寄存器,而packet_size 在机器的各种其他状态中会在您在上面看到的状态之前递增。

我已经通过切换 if 语句条件来绕过错误,但仍然想了解为什么这会改变任何事情。

【问题讨论】:

  • statenext_state 的位范围是多少? GET_PAYLOAD_DATAGET_CHKSUM2 的值是多少?
  • state 和 next_state 是 4 位(reg [3:0] state,next_state),GET_PAYLOAD_DATA 和 GET_CHKSUM2 是分别指定为 4'd5 和 4'd7 的参数。
  • 假设您使用组合块和单独的块来分配翻牌,那么packet_size &lt;= packet_size + 1; 应该是next_packet_size = packet_size + 1; 保持阻塞(=) 和非在单独的始终块中阻塞(&lt;=)分配。清理它,让我们知道这是否有帮助。
  • @Greg 这很奇怪,但是我通过将条件语句的顺序从if (packet_size &lt; payload_length) begin 切换到if (payload_length &gt; packet_size) begin 来解决这个错误。对我来说,为什么合成器会在它切换时工作,而不是在原始时工作,这对我来说真的没有多大意义。
  • 能否展示packet_size和payload_length的声明

标签: verilog xilinx synthesis


【解决方案1】:

有一些错误会立即出现在代码中,虽然它们可能无法解决这个问题,但它们需要被纠正,因为这会导致模拟和硬件测试的差异。

nextstate 逻辑需要位于不同的始终块中,该块不会根据时钟的位姿而改变。敏感度列表需要包括“状态”和/或“*”之类的内容。如果您希望像现在一样注册 nextstate 逻辑(您不这样做),您应该使用非阻塞赋值,这在下面提供的 cummings 论文中有大量描述。

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf

代码应如下所示:

always @ (*) begin
    //case statements with various states
    GET_PAYLOAD_LEN:
        begin
            if (rx_toggle == 1) begin
                packet_size_en = 1'b1;
    //these will need to be changed in a similar manner 
                addr <= 3;
                din <= rx_byte_buffer;
                payload_length <= rx_byte_buffer;
    /////////////////////////////////////////////////////
                next_state = GET_PAYLOAD_DATA;
            end else begin
                next_state = GET_PAYLOAD_LEN;
            end
        end

always@(posedge clk) begin 
   if(pcket_size_en)
       packet_size <= packet_size +1 ;
end 

另外,我要尝试的第一件事是通过将它们设为 reg 类型来使它们成为定义的长度(我假设您不需要带符号的数字,因此它在模拟上应该没有区别),在生成块之外,你应该尽量不要让合成玩弄整数。

【讨论】:

  • 组合块只能使用块分配。请参阅所引用论文的第 11 节。一个好的做法是使用“next”作为网络名称的前缀(或后缀)来分配翻牌。例如addr &lt;= next_addr;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 2019-01-26
相关资源
最近更新 更多