【问题标题】:Prefered syntax for verilog module declarationverilog 模块声明的首选语法
【发布时间】:2016-08-24 06:41:33
【问题描述】:

我对 FPGA 比较陌生,我正在寻找有关在 Verilog 中声明模块的现代最佳实践的一些指导。

我见过两种在 verilog 中声明模块的方法。第一个让我想起了Traditional C,比如examples on wikipedia

module toplevel(clock,reset);
    input clock;
    input reset;

    /* snip */
endmodule

而替代语法将输入/输出说明符作为参数列表的一部分,与 VHDL 不太相似,如this example

module fadder(
    input a,         //data in a
    input b,         //data in b
    input cin,       //carry in
    output sum_out,  //sum output
    output c_out     //carry output
);

/* snip */
endmodule

对于新编写的verilog代码,首选哪种语法?在这种情况下,“首选”是指在标准或相关材料中编写的内容(明确编写,或通过标准中给出的示例隐含),或编写在备受推崇的风格指南中。这个问题不是在询问个人喜好!

【问题讨论】:

    标签: syntax verilog


    【解决方案1】:

    第二个语法形式被缩进以替换第一个语法形式。如果您查看 1364-2001 Verlog LRM 以及当前的 1800-2012 SystemVerilog LRM,您会注意到模块声明的所有示例都使用第二种形式。第一种形式仅用于遗留,但不幸的是,转换教科书和课程材料的时间比预期的要长。

    这种较新(或 ANSI 样式)语法的主要好处是您只需在一个地方声明您的端口名称。使用较旧的语法,您必须最多声明一个端口名称 3 次;一次用于位置顺序,另一次用于端口方向,如果端口需要不是电线,则第三次声明其数据类型。

    【讨论】:

    • 接受这个,因为解释的理由。感谢这两个答案。
    【解决方案2】:

    第二个是首选。这是在 Verilog 2001 中引入的。这通常称为“ANSI 样式”。

    当我教 Verilog 时,我都教,但建议所有新代码使用 ANSI 样式。 (并且提到我只教第一种样式,以便学生能够理解遗留代码。)

    如果你继续使用 System-Verilog,你会发现有些东西无论如何只适用于 ANSI 样式。

    【讨论】:

    • SystemVerilog 不支持非 ANSI;请参阅IEEE Std 1800-2012 § 23.2.2.1。 ANSI 是首选样式
    • @Greg,Matthew 所传达的是某些新的 SystemVerilog 功能仅适用于 ANSI 样式的端口。例如,您不能使用非 ANSI 样式端口定义通用 interface 端口 - 因为 LRM 仅使用 ANSI 样式端口为该功能创建合成器。
    • @dave_59,我想我第一次读到最后一行时会错过。我还错过了非 ANSI 不支持通用 interface 等某些功能的细节。
    • (和@dave_59) - 有点迂腐,我知道,但短语 'ANSI-style' 不正确,并且在这种情况下没有出现在 2005 LRM 中。它似乎是由其他人编造的(无论如何,“ANSI C”仅指临时 C89)。新型端口列表不是 C 风格的,因为它们允许使用逗号分隔的列表,而 C 不允许。
    • @EML, IEEE 1800-2017 在第 23.2.1 节模块头定义中说 模块头定义有两种样式,非 ANSI 头和 ANSI 头。 style 这个词无论如何都不是一个正式的定义——它的意思是“本着”
    【解决方案3】:

    第二种模式是首选,但在某些情况下您可能想要使用第一种模式。这是如果您需要对参数进行大量复杂计算以达到正确的端口宽度。下面只是一个小的人工示例。是的,您可以将 localparam 替换为它们的表达式,但这可能会使您的代码不可读。
    我认为这是(系统)Verilog 的遗漏之一,您不能在 #(parameter.. 定义之后使用 local_param。

    module example 
    #(parameter       
       L2DEPTH   =  8,
       OFFSET    =  2
    )
    (siga,sigb,sigc,sig_out);
    localparam DEPTH = 1<<L2DEPTH;
    localparan TOP   = DEPTH+OFFSET;
    localparam BOT   = DEPTH-OFFSET;
    localparam DBLDEPTH   = 2<<L2DEPTH;;
    input  [  L2DEPT-1:0] siga;
    input  [     TOP-1:0] sigb;
    input  [     BOT-1:0] sigc;
    output [DBLDEPTH-1:0] sig_out;
    

    【讨论】:

    • 不正确。您当然可以在 parameter_port_list 中声明 localparam
    • @dave_59 提供另一种观点,当从真正应该在`define 中的参数中派生出更复杂的东西时,并不总是可以将它放在参数列表中。例如,假设模块的输出是压缩结构类型,其字段宽度取决于输入参数。这不能在包中,因为包不能被参数化。因此,类型定义需要介于输入参数声明和输出信号声明之间。
    • 同意,在极少数情况下,使用 ANSI 样式的端口会更加困难,但您刚才提到的情况并非如此。 module DUT #(int P=1, Q= 3, type T = struct packed {bit [P:Q] d;})(input T fff);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多