第二,如果循环在verilog中不工作,并且生成了锁存。如何修复这些问题?

第二,如果循环在verilog中不工作,并且生成了锁存。如何修复这些问题?,verilog,Verilog,我是Verilog的新手。我尝试了下面的代码,将“任务”调用到if循环中。。语法正确。但是,当我以choice作为010执行行为模拟时,循环不起作用。输出显示为全零,合成报告显示已生成锁存。如何修复这两个问题 module a(choice,data1,data2,result); input[2:0]choice; input[6:0]data1; input[8:0]data2; output[8:0]result; reg[8:0]reg_result; wir

我是Verilog的新手。我尝试了下面的代码,将“任务”调用到if循环中。。语法正确。但是,当我以choice作为010执行行为模拟时,循环不起作用。输出显示为全零,合成报告显示已生成锁存。如何修复这两个问题

module a(choice,data1,data2,result);
  input[2:0]choice;
  input[6:0]data1;
  input[8:0]data2;
  output[8:0]result;

  reg[8:0]reg_result;

  wire[3:0]choice;
  wire[6:0]data1;
  wire[8:0]data2;
  wire[8:0]result;

  initial///initailllllllllllllllllllllllllll
  begin
    reg_result=0; //declaring output register to 0 initially
  end

  always @(data1 or data2 or choice )
  begin
    if(choice==001)////if loop 1
    begin
      taskoperation(data1,reg_result);///load result from task 
    end
    if(choice==010)//when choice is given as 010 the simulated output gives me all    
    begin//zeroes in   result(output reg) 
      taskoperation(data2,reg_result);
    end
  end
  //task operation
  task taskoperation(
    input [8:0]datainput;
    output [8:0]dataoutput
  );
    dataoutput[8:0]=~(datainput[8:0]);//taskoperation
  endtask

  assign result=reg_result;

endmodule
闩锁

闩锁可能是由于使用2个if语句作为选择器而生成的。这些应该是声明

case (choice) 
 3'b001 : 
     begin
         taskoperation(data1,reg_result);
     end 
 3'b010 : 
     begin
         taskoperation(data2,reg_result);
     end
 default : $display("Error in choice");  //Know when there are other issues!
 endcase
为什么010不起作用

请参见我的案例陈述中如何使用3'b001和3'b010来表示案例?通过包含大小前缀3,我指示需要该总线的位数。通过包含b,我表示我希望我的数字被解释为二进制值。所以3'b001等于十进制值1。同样,3'b010被解释为2。如果我只写010而没有任何前缀,编译器会认为我说的是十进制值,并将其解释为十进制的10。这就是你可能出错的地方。010案件根本就没有联系到。这个故事的寓意是,当用文字编码时,总是要写前缀

注释

请注意,如果您确实认为if语句是作业的正确工具,请确保始终包含else块,以避免闩锁生成

文字:

另一个案例参考:

最后是关于锁存发生原因的初学者参考:

010被推断为十进制,使其值为10。用布尔基文本定义它;3'b010。您还应该将001改为3'b001

SystemVerilog遵循相同的规则。这是§5.7.1整型文字常量的定义

整数文字常量可以以十进制、十六进制、八进制或二进制格式指定。 有两种形式可以表示整型文字常量。第一种形式是简单的十进制数,应指定为0到9的数字序列,可以选择以加号或减号一元运算符开头。第二种形式指定了一个基于文字的常量,该常量最多由三个标记组成:可选大小常量、撇号字符'、ASCII 0x27,后跟一个基本格式字符,以及表示数字值的数字。替换这三种代币是合法的

导致闩锁的原因有两个:

choice==010意味着{29'b0,choice}==32'd10,这永远不会是真的,并且将在sunthesis期间进行优化。 当选项不是1或2时,没有其他条件。这意味着reg_结果将保持其值。由于这是在组合逻辑中,所以可以推断出锁存器。 将ifchoice==010转到else ifchoice==2'b010,然后添加一个else条件,为reg_结果赋值

修复语法错误:input[8:0]datainput;需要输入[8:0]数据输入,分号到逗号

其他建议:

除非您需要遵守严格的Verilog95标准,否则请始终使用@*而不是@data1或data2或choice。当灵敏度列表较长时,使用@*有助于防止推断锁存。提到 在打算合成时,尽可能使用函数而不是任务。任务允许不可合成的时间阻塞。 使用ANSI样式的端口声明。仅Verilog95需要非ANSI样式。例子:
module a(
input      [2:0] choice,
input      [6:0] data1,
input      [8:0] data2,
output reg [8:0] result );

Verilog-2001支持ANSI样式。

每当您有非顺序块时,都会生成锁存。任何始终块在灵敏度列表中都没有@posedge或@negedge,并且RTL中有一个可能的代码路径,导致信号保留其旧值

例如:

if (foo)
  bar = 1;
// no else
在这种情况下,将推断闩锁,因为如果foo==0,则bar将在有状态时保留其值。要解决此问题,请使用else:

if (foo)
  bar = 1;
else
  bar = ~fred;
或者,如果决策树很复杂,请指定一个默认值,并在以后覆盖它:

bar = ~fred;
if (foo)
  bar = 1;
后者经常与状态机一起使用,在状态机中很难确保每个信号都有完整的case/if/else树