【问题标题】:Generate statement inside verilog task在verilog任务中生成语句
【发布时间】:2013-05-31 15:10:34
【问题描述】:

我想在任务中使用生成语句。以下代码给出编译错误(iverilog)。

task write_mem; //for generic use with 8, 16 and 32 bit mem writes
      input [WIDTH-1:0] data;
      input [WIDTH-1:0] addr;
      output [WIDTH-1:0] MEM;
      integer i;

      begin
         generate
            genvar j;
            for(j=0; j<i;j++)
            MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
         endgenerate
      end
endtask // write_mem

我还尝试将generate 放在integer i 行之后,但仍然会产生错误。有什么想法吗?

编辑:我还尝试在上面的代码中将genvar 声明放在begingenerate 语句之间。它仍然产生编译器错误

提前致谢,

杰·奥拉宾德

【问题讨论】:

    标签: verilog hdl


    【解决方案1】:

    您尝试的操作是不可能的 - 生成区域(generate..endgenerate 块)只允许在模块描述(也称为“顶级”)中,即您拥有参数、电线、总是和inital-regions 等(参见 IEEE Std. 1364-2005 中的语法 12-5)。在任务中,生成区域是例如和赋值语句一样无效。

    但是,您可以在任务中使用非生成 for 循环(这也是可综合的)。

    无论哪种方式,您都不能在可综合代码中从 0 计数到 i-1,因为“i”不是恒定的。另请注意,j++ 不是有效的verilog,您必须改写j=j+1。最后,您可能希望使用非阻塞赋值 (

    【讨论】:

    • 非常感谢@CliffodVienna :)
    • @CliffodVienna 关于 j++ 的观点。另外,我从always 块中调用此任务。所以阻塞赋值应该能够产生可综合的代码,对吧?
    • @JayAurabind 使用的分配类型应该反映从哪里调用任务。 always @* 组合使用 = 阻塞。 always @(posedge clk) 顺序使用 &lt;= 非阻塞。
    • @Morgan 如果阻塞和非阻塞之间的区别这么简单,那么综合工具可以为您完成。在 Verilog 中,每个构造总是有两个含义:模拟语义和综合语义。如果使用得当,这两种语义在这两个域中都会产生相同的行为。如果使用不当,可能会导致仿真综合不匹配。参见例如stackoverflow.com/a/4774450/2213720sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf 了解更多详细信息以及阻塞和非阻塞语义的定义。
    • @Morgan,综合工具确实以不同的方式处理阻塞和非阻塞分配,即,当变量在分配后在 always 块中被访问时。模拟还以不同的方式处理阻塞和非阻塞分配:阻塞分配立即执行,非阻塞分配在时隙结束时执行。如果使用得当,这会在仿真和综合中产生相同的行为。但是为了正确使用它,必须理解语义。恕我直言,每个用例的指南无法帮助任何人理解(也(在)Cummings ;-)。
    【解决方案2】:

    genvars 应该在 generate 语句之前定义:

    genvar j;
    generate
      for(j=0; j<i;j++)
        MEM[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
    endgenerate
    

    虽然您在此处的使用看起来不需要一个 for 循环会完成的生成语句。

    正如@CliffordVienna 所指出的,生成语句用于基于编译时间常数构建层次结构和布线。即参数可以更改为可重用代码,但在给定的模拟中是恒定的。任务不包含层次结构,因此使用生成是无效的。

    任何可以展开的 for 循环都是可合成的,例如:

    task write_mem; //for generic use with 8, 16 and 32 bit mem writes
      input  [WIDTH-1:0] data;
      input  [WIDTH-1:0] addr;
      output [WIDTH-1:0] mem;
      integer i = WIDTH / 8; // CONSTANT   
    
      begin
        for(j=0; j<i;j++) begin
          mem[addr+(i-j-1)] = data[(j*8):((j*8) + 8)-1];
        end
      end
    endtask // write_mem
    

    任务是可合成的,只要它们不包含任何时间控制,而您的任务不包含。根据给出的信息,这应该是可综合的。

    注意:我会将数据宽度和地址宽度分开,它们现在可能相同,但您可能希望转移到 8 位寻址和 16 位数据。

    【讨论】:

    • generate 之前声明genvar 也会产生编译器错误。对于任务,必须首先定义所有变量,然后在 begin...end 块中定义主语句,对吗?如果是这样,那么 genvar 内的 begin..end 声明违反了该规则,不是吗?
    • 我的真实代码实际上有语句`i = WIDTH / 8;`这将使i保持不变,对吧?这个任务也是从always 块中调用的。所以这将是可合成的,不是吗?
    • 非常感谢@Morgan :)
    猜你喜欢
    • 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
    相关资源
    最近更新 更多