如何在Verilog中重用多个always块

时间:2015-12-10 12:25:47

标签: verilog

以下是始终阻止代码。

我需要使用相同的代码11次,具有相同的功能但是在不同的变量上。那么我该如何重用代码?

call setx -m ORACLE_HOME "C:\Servers\oc4j_extended_101350" 
call C:\Servers\oc4j_extended_101350\bin\oc4j -start 
call REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V ORACLE_HOME

命名模式 -

  • always @(posedge tconClk or negedge tconRst_n) begin if(~tconRst_n) begin pulse_cnt <= 0; pulse_start = 0; start_written = 0; pulse_width <= 'h271; end else if(~pulse_rst) begin pulse_cnt <= 0; pulse_start = 0; end else begin if(start_signal) begin // start_written = 0; pulse_width <= (pulse_start) ? pulse_width : START_PW; pulse_start = 1; end pulse_cnt <= (pulse_start) ? (pulse_cnt + 1) : pulse_cnt; end end tconClk很常见,
  • tconRst_npulse_cnt0pulse_cnt1
  • 10pulse_width0pulse_width1
  • 10(数组),
  • pulse_start[0:10](数组),
  • start_written[0:10](数组),
  • pulse_rst[0:10](数组),
  • start_signal[0:10](没有模式,每个11个总块的名称不同)

注意 -

  1. 定义宏不起作用,因为此代码包含许多verilog标记。

  2. 我无法生成代码模块,因为always块中使用的信号也用于代码的其他部分。因此,如果我制作模块,那么我将无法确保正确的寄存器或电线连接到模块。 (就像模块输出端口必须是导线一样,但是相同的信号已被用作代码其他部分的reg)

3 个答案:

答案 0 :(得分:1)

您可以使用emacs脚本verilog-mode来封装模块中的RTL并使用AUTO_TEMPLATE。如下所示(未经测试)然后在emacs内执行verilog-batch-auto

/* PulseModule AUTO_TEMPLATE "\([0-9]+\)$" (
     .pulse_cnt(pulse_cnt@),
     .pulse_width(pulse_width@),
     .pulse_start(pulse_start[@]),
     .start_written(start_written[@]),
     .pulse_rst(pulse_rst[@]),
     .start_signal(start_signal[@]),
     .tconClk(tconClk),
     .tconRst_n(tconRst_n)
    );
*/
PulseModule pm_0 (/*AUTOINST*/ .start_pulse_width(START_PW) );
PulseModule pm_1 (/*AUTOINST*/ .start_pulse_width(OTHER_START_PW) );
...
PulseModule pm_10 (/*AUTOINST*/ .start_pulse_width(SOME_OTHER_START_PW) );

还有各种嵌入式代码(例如Perl的EP3,Ruby的eRuby / ruby_it,Python的prepro等),可以生成所需的代码。< / p>

SystemVerilog增强了宏的功能。对您而言,``功能将使您的工作更轻松。见IEEE Std 1800-2012§22.5.1`define。

多行宏很难调试。虽然可以将RTL作为一个宏,但我强烈建议将其放在模块中并让宏实例化宏。以下某些湖泊(未经测试):

`define PULSEMACRO(id,val) \
   PulseModule pm_``id( \
     .pulse_cnt(pulse_cnt``id), .pulse_width(pulse_width``id), \
     .pulse_start(pulse_start[id]), .start_written(start_written[id]), \
     .pulse_rst(pulse_rst[id]), .start_signal(start_signal[id]), \
     .start_pulse_width(val) \
     .tconClk(tconClk), .tconRst_n(tconRst_n) )

此实例化如下。请注意,生成for循环不起作用。在生成块之前评估宏。

`PULSEMACRO(0,START_PW);
`PULSEMACRO(1,OTHER_START_PW);
...
`PULSEMACRO(10,SOME_OTHER_START_PW);

SystemVerilog还可以通过模块端口传递多维数组。因此,您可以将reg [PULSE_CNT_WIDTH-1:0] pulse_cnt0,...,pulse_cnt10重命名为logic [PULSE_CNT_WIDTH-1:0] pulse_cnt [11]。通过此转换,您可以使用生成循环。

或者,您可以将pulse_cnt折叠为大型总线reg [PULSE_CNT_WIDTH*11-1:0] pulse_cnt,然后使用位切片进行索引pulse_cnt[PULSE_CNT_WIDTH*index +: PULSE_CNT_WIDTH]。位切片也与Verilog兼容。请参阅What is `+:` and `-:`?Indexing vectors and arrays with +:

答案 1 :(得分:0)

always放在generate语句中。你应该在SO上找到很多例子:here。您仍然需要修改代码,这可能比修改模块实例化更容易。

您的代码此刻已被破坏,因为pulse_rst在时钟边缘之前进行了测试,并且它不在敏感度列表中。您应该将其放在列表中,或重新编码块。请注意,Verilog中存在两个异步控件和一个时钟的问题;通过异步设置查看&#34; verilog flops并重置&#34;,或者再问一个不同的问题。

答案 2 :(得分:0)

我认为你仍然可以使用宏。将这些非公共变量更改为宏,例如将pulse_cnt更改为`pulse_cnt。将它们放入文件并将其用作包含文件。

例如你的代码,

always @(...) 
begin
  `pulse_cnt <= 0;
  // ...
end

将此模板放入名为my_always.v

的文件中

然后重复使用其他文件/模块中的代码,如下所示:

`define pulse_cnt pulse_cnt0
`include "my_always.v"
`undef pulse_cnt

`define pulse_cnt pulse_cnt1
`include "my_always.v"
`undef pulse_cnt

//... and so on