【问题标题】:Verilog: Can you put "assign" statements within always@ or begin/end statements?Verilog:你能把“assign”语句放在always@或begin/end语句中吗?
【发布时间】:2009-10-29 01:39:52
【问题描述】:

这是允许的吗?

input w;
     input [8:0]y;
     output reg [8:0]x;
     always@(w)
     begin


     //x[0] or A is never on in any next state
     assign x[0] = 0;
     assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B
     assign x[2]= (y[1]&~w); //C
     assign x[3]= (y[2]&~w); //D
     assign x[4]= (y[3]&~w) | (y[4]&~w); //E
     assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F
     assign x[6]= (y[5]&w);
     assign x[7]= (y[6]&w);
     assign x[8]= (y[7]&w) | (y[8]&w);

     end

【问题讨论】:

标签: verilog


【解决方案1】:

可以,这称为“程序连续分配”。它覆盖了普通的程序分配,在您发布的代码中似乎没有调用它们。我不确定它们是否可以合成,但无论如何我都没有理由使用它们。

关于您的代码的注释 - 您的敏感度列表中缺少 y:例如,always @( w or y )always @(*) 更安全。

【讨论】:

  • 程序连续分配已被弃用为 SystemVerilog 的一部分。它们只是不是一个好主意,因为它们不可合成,并且会使模拟变得一团糟。
【解决方案2】:

根据 Marty 的回答,您应该阅读 IEEE Verilog 标准(例如 1364-2005)的第 9.3 节,其中描述了“程序连续分配”。该规范允许在 always 块中使用 assign 语句。但是,根据我的经验,这种情况非常罕见。

您的代码的另一个问题是它在我尝试过的两个不同的模拟器中出现编译错误。两者都会生成错误消息,指出不能在赋值的左侧使用位选择或部分选择。

另一种可能的解决方案是去掉always 块,而只使用简单的连续赋值。

input w;     
input [8:0] y;
output [8:0] x;
assign x[0] = 0;     
assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B     
assign x[2]= (y[1]&~w); //C     
assign x[3]= (y[2]&~w); //D     
assign x[4]= (y[3]&~w) | (y[4]&~w); //E     
assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F     
assign x[6]= (y[5]&w);     
assign x[7]= (y[6]&w);     
assign x[8]= (y[7]&w) | (y[8]&w);

【讨论】:

    【解决方案3】:

    程序连续的assign 语句旨在成为编写类似多路复用器的行为的优化方式。例如,如果您有

    always @(A or B or select)
      if (select)
        out = A;
      else
        out = B;
    

    你可以这样写

    always @(select)
       assign out = A;
     else 
       assign out = B;
    

    但是人们不喜欢处理敏感度列表,所以在 Verilog 中添加了@(*),并在 SystemVerilog 中添加了always_comb

    但这种结构的真正杀手是很多人会编写类似的代码

    always @(*)
       assign out = A;
    

    这模拟得很好,但现在你的性能会受到双重损失,因为assign 语句已经对 A 中的变化敏感,always 块也是如此。这会重复执行程序 assign 语句替换相同的 RHS。

    【讨论】:

      【解决方案4】:

      Assign 是一个连续赋值语句,在 Verilog 中与连线一起使用。分配语句不会进入程序块(例如总是)。可以在 always 块中给寄存器赋值。

      赋值语句可以看成:

       always @(*)
      

      电线声明。

      【讨论】:

        【解决方案5】:

        是的,但你不想这样做。由于 x[] 不依赖于 x[] 顺序无关紧要。只需使用

        【讨论】:

          【解决方案6】:

          不需要在程序块内使用assign(在这种情况下总是)

          Assign 是一个连续的赋值,它必须超出程序块。

          【讨论】:

            【解决方案7】:
            1. 从电路层面思考:这个 always(w) begin ..... end ,所以它里面的每个代码都会在 w 改变时被激活,即它下降或上升。
            2. assign 语句需要将其分配给某些线路或 reg 输出的引脚/端口
            3. 它是一个完整的组合电路,我无法看到它如何仅在 w 处激活,即谁/什么电路将使其仅在 w 上升或下降时改变
            4. 无论如何,您不能使用 assign 语句将 reg 输出分配给某些线/reg 输出,因为正如我所说,它要求您只分配 pin/port
            5. 无论如何,如果您选择基本的verilog而不是所谓的“程序连续分配”,我想使用相同的方法很奇怪。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多