2301_80028052 2023-12-07 20:05 采纳率: 0%
浏览 7

Verilog代程序always语句里面的bug

请问这份代码哪里有问题啊?rst信号和两个key信号触发了但是没有执行对应的行为。我在仿真测试里面,输出没有任何问题,但是上板子就不行了


module GetData(
  input rst,      //数据复位
  input stage,    //0-输入状态    1-滚动显示状态
  input key_get,  //输入按键
  input key_ok,    //单个数字输入完毕按键

  output [15:0]data
);

  reg [15:0]dataArray = 16'hf000;  //十六进制A代表字母U  F代表初始化值
  assign data = dataArray;

  reg [3:0]dataCount = 4'b0000; //记录按下key_get的次数


 always @(posedge key_get,posedge rst) begin   //按下get或rst
    if(rst)begin
      dataArray <= 16'hffff;
      dataCount <= 0;
    end
    else begin   
      if(!stage)begin       //输入状态
        if(dataCount == 4'hA)  dataCount <= 4'b0000;  //超出数据范围(最大是a)
        else dataCount <= dataCount +1; 
      end
    end
  end

  always @(posedge key_ok) begin
    if(!stage)begin       //输入状态
        dataArray <= dataArray<<4;
        dataArray[3:0] <= dataCount;
        dataCount <= 4'b0000;
    end
  end

endmodule
  • 写回答

2条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-12-07 20:25
    关注

    所有内容均由人工智能模型输出,其内容的准确性和完整性无法保证,不代表我的态度或观点。

    该回答引用ChatGPT-3.5,仅为您提供参考,不保证完全正确
    在Verilog代码中,一些常见的问题可能导致在仿真测试中正常工作,但在实际硬件上出现问题。以下是可能导致问题的一些原因:

    1. 时序问题: 在FPGA或ASIC中,时序非常关键。在你的代码中,你使用了两个不同的always块,并且两者都有posedge触发条件。确保这两个块的触发条件和时序是正确的。在FPGA中,时序问题可能导致某些行为无法按预期执行。

    2. 时钟同步问题: 如果你的key_getrst信号不是来自同一个时钟域,可能会导致时钟同步问题。确保所有时钟和触发信号都处于相同的时钟域。

    3. 电源/复位问题: 确保你的硬件平台上的电源和复位信号是稳定的,而且与你的代码期望的一致。

    4. 寄存器的宽度: 在你的always @(posedge key_get,posedge rst)块中,你使用了<=来更新dataCount。请确保dataCount的宽度足够,以防止溢出或意外行为。可以尝试将dataCount声明为reg [3:0] dataCount = 4'b0000;,确保其宽度正确。

    5. always块的灵敏度列表:always块的灵敏度列表中使用了posedge key_get, posedge rst。这表示只有在key_getrst信号上升沿时才执行代码。如果你的硬件平台上的信号存在抖动,可能导致触发条件不满足。可以尝试使用posedge key_get or posedge rst,以便在任何一个信号上升沿时执行代码。

    如果你仍然无法解决问题,可能需要更详细地检查仿真和实际硬件上的波形,并使用调试工具来识别问题的根本原因。


    该回答引用NewBing,仅为您提供参考,不保证完全正确
    您好,这是Bing。我尝试了一下您的代码,发现了一些可能的问题:

    • 您的rst信号是低电平有效的,但是您的always块是在rst的上升沿触发的,这可能导致复位不正确。您应该改为negedge rst,或者将rst信号改为高电平有效。
    • 您的key_get和key_ok信号可能需要一个去抖动电路,否则可能会出现多次触发的情况。您可以参考这篇文章¹,里面有一个简单的去抖动电路的例子。
    • 您的dataCount变量可能需要一个清零的条件,否则当stage信号为1时,它会一直保持原来的值。您可以在always块中添加一个else if (stage) begin dataCount <= 0; end的语句,或者在rst信号有效时也清零dataCount。

    源: 与必应的对话, 2023/12/7
    (1) Verilog初级教程(10)Verilog的always块 - CSDN博客. https://blog.csdn.net/Reborn_Lee/article/details/107052261.
    (2) verilog 语法常见错误有哪些? - 知乎. https://www.zhihu.com/question/486117307.
    (3) 【Verilog】一、Verilog的always使用 - CSDN博客. https://blog.csdn.net/weixin_43699738/article/details/102469273.
    (4) 我的 FPGA 学习历程(15)—— Verilog 的 always 语句综合 - 夏日时光 - 博客园. https://www.cnblogs.com/SummerSunnyDay/p/11543929.html.
    (5) hdlbits系列verilog解答(always块if语句)-31-CSDN博客. https://blog.csdn.net/zuoph/article/details/134191439.


    该回答引用文心大模型3.5,仅为您提供参考,不保证完全正确
    根据你提供的代码,问题可能出现在两个地方:

    1. 输入信号的触发方式不对。在 always 块中,你使用 posedge 关键字来触发,这意味着你希望在上升沿时执行某些操作。然而,你的 key_get 和 rst 信号可能并非上升沿触发的。你需要根据你的硬件或者你的测试平台来决定你的触发方式。
    2. 第二个问题是,你在 always @(posedge key_ok) 块中,当 key_ok 信号上升沿到来时,你试图将 dataCount 重置为 4'b0000,但这是在 key_get 信号的上升沿后面触发的,所以可能会产生一些问题。

    为了解决这两个问题,我为你修改了代码:

    module GetData(
      input rst,      //数据复位
      input stage,    //0-输入状态    1-滚动显示状态
      input key_get,  //输入按键
      input key_ok,    //单个数字输入完毕按键
     
      output reg [15:0]data
    );
     
      reg [15:0]dataArray = 16'hf000;  //十六进制A代表字母U  F代表初始化值
      assign data = dataArray;
     
      reg [3:0]dataCount = 4'b0000; //记录按下key_get的次数
     
     always @(posedge rst or posedge key_get) begin   //上升沿触发
        if(rst)begin
          dataArray <= 16'hffff;
          dataCount <= 0;
        end
        else if(key_get) begin   //在key_get的上升沿触发
          if(!stage)begin       //输入状态
            if(dataCount == 4'hA)  dataCount <= 4'b0000;  //超出数据范围(最大是a)
            else dataCount <= dataCount +1; 
          end
        end
      end
     
      always @(posedge key_ok) begin
        if(!stage)begin       //输入状态
            dataArray <= dataArray<<4;
            dataArray[3:0] <= dataCount;
            dataCount <= 4'b0000;
        end
      end
    endmodule
    

    希望这个修改后的代码可以解决你的问题。如果问题仍然存在,你可能需要检查你的硬件或者测试平台是否正常工作。


    该回答引用讯飞星火认知大模型,仅为您提供参考,不保证完全正确
    这段代码中存在一个逻辑错误。在always @(posedge key_get, posedge rst)块中,当rst信号为高电平时,dataArraydataCount应该被重置为初始值。但是在这个块中,只有rst信号被处理了,stage信号没有被处理。因此,当stage信号为低电平时,dataArraydataCount的值不会改变,导致程序行为不符合预期。


    为了解决这个问题,你需要在else语句中添加对stage信号的处理。修改后的代码如下:

    module GetData(
      input rst,      //数据复位
      input stage,    //0-输入状态    1-滚动显示状态
      input key_get,  //输入按键
      input key_ok,    //单个数字输入完毕按键
     
      output [15:0]data
    );
     
      reg [15:0]dataArray = 16'hf000;  //十六进制A代表字母U  F代表初始化值
      assign data = dataArray;
     
      reg [3:0]dataCount = 4'b0000; //记录按下key_get的次数
     
     
     always @(posedge key_get, posedge rst) begin   //按下get或rst
        if(rst)begin
          dataArray <= 16'hffff;
          dataCount <= 0;
        end
        else begin   
          if(!stage)begin       //输入状态
            if(dataCount == 4'hA)  dataCount <= 4'b0000;  //超出数据范围(最大是a)
            else dataCount <= dataCount +1; 
          end
          else if(stage) begin  //滚动显示状态
            dataArray <= dataArray<<4;
            dataArray[3:0] <= dataCount;
            dataCount <= 4'b0000;
          end
        end
      end
     
    endmodule
    

    这样修改后,当rst信号为高电平时,dataArraydataCount会被重置为初始值,同时在stage信号为低电平时,dataArraydataCount的值也会被更新。


    该回答引用通义千问大模型,仅为您提供参考,不保证完全正确
    这份 Verilog 代码中存在几个问题,我将列出这些问题并提供相应的解决方案。

    1. 非阻塞赋值和复位信号:在 always @(posedge key_get,posedge rst) 中的 if(rst) 分支里使用了非阻塞赋值(<=),这可能导致复位操作不会立即执行。请将这些非阻塞赋值更改为阻塞赋值(=)。
    if (rst) begin
      dataArray = 16'hffff;
      dataCount = 4'b0000;
    end
    
    1. 使用 assign 语句更新输出:由于您希望数据能够根据输入变化而实时更新,因此建议移除 assign 语句,并在 always 块中直接对 output 数据进行赋值。
    // 删除这行
    // assign data = dataArray;
    
    // 在 always @(posedge key_ok) 结尾添加以下内容
    always @(posedge key_ok) begin
      // ...
      data <= dataArray;
    end
    
    1. stage 输入控制逻辑:在两个 always 块中都包含了针对阶段输入(stage)的条件判断。考虑到不同阶段的操作是相互独立的,可以考虑将这两个 always 块拆分为四个单独的 always 块,每个块负责一个特定的功能。

    以下是修改后的代码:

    module GetData(
      input rst,      //数据复位
      input stage,    //0-输入状态    1-滚动显示状态
      input key_get,  //输入按键
      input key_ok,    //单个数字输入完毕按键
     
      output [15:0]data
    );
     
      reg [15:0]dataArray = 16'hf000;  //十六进制A代表字母U  F代表初始化值
      //assign data = dataArray;
    
      reg [3:0]dataCount = 4'b0000; //记录按下key_get的次数
    
      always @(posedge key_get or posedge rst) begin   //按下get或rst
        if (rst) begin
          dataArray = 16'hffff;
          dataCount = 4'b0000;
        end else if (!stage) begin       //输入状态
          if (dataCount == 4'hA)  dataCount = 4'b0000;  //超出数据范围(最大是a)
          else dataCount = dataCount +1; 
        end
      end
    
      always @(posedge key_ok) begin
        if (!stage) begin       //输入状态
            dataArray = dataArray << 4;
            dataArray[3:0] = dataCount;
            dataCount = 4'b0000;
            data = dataArray;
        end
      end
    endmodule
    

    请尝试以上修复后查看是否解决了您的问题。如果还有其他问题,请随时提问。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月7日