2013-07-18 59 views
1

我想根据实例化模块时设置的参数设置参数。我有以下几点。生成块中的系统Verilog参数

module foo #(WORDS = 8); 

parameter P00 = 33; 
logic [7:0] tmp; 

generate 
    case (WORDS) 
    4: begin : A 
     assign tmp = 8'haa; 
     parameter P00 = 4; 
     end 
    8: begin : B 
     assign tmp = 8'hbb; 
     parameter P00 = 8; 
     end 
    16: begin : C 
     assign tmp = 8'hcc; 
     parameter P00 = 16; 
     end 
    default: begin : D 
       assign tmp = 8'hdd; 
       parameter P00 = 8; 
      end 
    endcase 
endgenerate 

initial begin 
    $display ("WORDS = %d", WORDS); 
    $display ("tmp = %h", tmp); 
    $display ("P00 = %d", P00); 
end 

endmodule 

我预计会重新定义P00时出现错误,但它会编译并运行并显示下列内容。

WORDS =  8 
tmp = bb 
P00 = 33 

如果我评论“参数P00 = 33”赋值,我会得到一个“标识符P00尚未声明”。错误。

看起来生成块被忽略。这里有什么问题?

+1

如果我正确地阅读了语言规范,实际上当您在生成块中使用参数类型时,实际上是在不同范围内创建新参数。它指出,“在[生成块]中,参数关键字应该是localparam关键字的同义词。”此外,“本地参数与参数相同,但它们不能通过...实例参数值赋值直接修改”。如果您有语言参考的副本并希望了解更多信息,请参阅第6.20.4节。它看起来像你需要一种不同的方法来解决这个问题。 –

+0

@丹 - 谢谢。我没有阅读上面的手册部分,但我没有看到生成块实际上创建了与模块不同的范围。我试图显示C.P00,但也没有工作。如果创建新范围,我如何访问它? – user2382841

+0

我对此并不十分清楚。我刚开始自己​​学习这门语言,但@Morgan似乎在下面有一个很好的答案。 –

回答

0

最近在这里有很多问题使用生成和不恰当地指定不确定是否写了一个新的教程没有正确地教导这些东西。

参数或Localparams不应该定义多次,它们是常量,因此不能更改值。我认为你也缺少模块foo中的参数关键字。

module foo #(
    parameter WORDS = 8 
); 

localparam P00 = WORD; 

这是常见的比例因子使用方法:

module foo #(
    parameter WIDTH = 8 
    parameter MAX_VALUE = 2**WIDTH 
); 

你所定义的样子,你应该只使用逻辑不参数持有的价值;

我会重写整个事情:

module foo #(WORDS = 8); 

logic [31:0] P00 = 33; 
logic [7:0] tmp; 

always @* begin 
    case (WORDS) 
    4: begin : A 
     tmp = 8'haa; 
     P00 = 4; 
     end 
    8: begin : B 
     tmp = 8'hbb; 
     P00 = 8; 
     end 
    16: begin : C 
     tmp = 8'hcc; 
     P00 = 16; 
     end 
    default: begin : D 
      tmp = 8'hdd; 
      P00 = 8; 
     end 
    endcase 
end 

使用产生的不必要的你正试图在这里实现什么。

+0

谢谢。您的评论很好,但确实有效,但并不完全符合我的需求。我使用了生成块,因为我只希望根据单词数来合成一个案例。该示例是模块的简化版本。参数的数量随着WORDS的数量而增加。也许我误解了你说的使用generate。另外,为了查看是否在生成块中设置了任何参数,添加了顶部设置P00 = 33的参数声明。我添加它会导致错误,但不会导致错误。 – user2382841

+2

@ user2382841我会仔细检查您的警告以及错误。生成对于根据参数或互连接线块创建层次结构(多个实例)很有用。如果输入是恒定的,则输出是恒定的,综合工具将很好地创建最小的硬件。如果P00是一个常数,如果逻辑(reg)或参数没有区别。 – Morgan

0

此作品(通常说,你需要让所有4生成块名称相同):

module foo #(WORDS = 8); 

parameter P00 = 33; 
logic [7:0] tmp; 

generate 
    case (WORDS) 
    4: begin : B 
     assign tmp = 8'haa; 
     parameter P00 = 4; 
     end 
    8: begin : B 
     assign tmp = 8'hbb; 
     parameter P00 = 8; 
     end 
    16: begin : B 
     assign tmp = 8'hcc; 
     parameter P00 = 16; 
     end 
    default: begin : B 
       assign tmp = 8'hdd; 
       parameter P00 = 8; 
      end 
    endcase 
endgenerate 

initial begin 
    $display ("WORDS = %d", WORDS); 
    $display ("tmp = %h", tmp); 
    $display ("P00 = %d", B.P00); 
end 

endmodule 
1

配售参数定义范围内的生成块生成新的本地相对于内的分层范围的参数生成块。 defparam通常是覆盖参数值的方式。然而IEEE std 1800-2012明确指出一defparam不能在§ 23.10.1实现它的父范围:

在或下一个生成块 实例层次结构的defparam言(见第27条)或实例的数组(见28.3.5和 23.3.2)不得改变该层级以外的参数值。

对于复杂的派生参数分配,可以使用函数。例如:

parameter P01 = FUNC01(WORDS,P00); 
function byte FUNC01(input byte w,p); 
/* ... */ 
endfunction 

这也是合法的:module foo #(parameter WORDS, P00=FUNC00(WORDS));

的挑战可能是,每个参数都需要有自己的功能。使用具有结构数据类型的参数是一种潜在的解决方法,可将分配分组为单个函数。这种方法需要通过模拟器,合成器和其他工具进行评估。例如:

typedef struct packed { 
    int sub00; 
    byte sub01; 
    /* ... */ 
bit [13:0] subNN 
} param_t; 
paramter param_t P = FUNC_P(/* inputs */); 

function param_t FUNC_P(/* inputs */); 
    param_t rtn; 
    /* assign all rtn.sub* */ 
    return rtn; 
endfunction 

logic [P.sub01-1:0] tmpvar; 

由于Morgan指出的那样,你可以定义大多数parameters作为logic和使用组合块。不过,我会强烈要求使用always_comb块而不是always @*来保证值的计算。正如在LRM § 9.2.2.2.2表示:直到在所推断的灵敏度 列表中的信号中出现的变化

always_comb自动在零时间执行一次,而总是 @ *等待。

+0

使用函数解决了我的问题。 – jgoeders