跳转至

实现第一个硬件

在学习各门编程语言的时候,老师都会使用像 hello world 这样的例子来进行引入,而本次我们学习硬件描述语言也不例外。

本节将会带大家实现一个最简单的两输入与门,来让大家了解各个硬件描述语言的基本编写方式和基本结构。

代码

module and_gate (
    input wire a_i,
    input wire b_i,
    output wire c_o
);
    assign c_o = a_i & b_i;
endmodule

可以看到,这段代码的 结构c++ 非常相似,我们在这里进行一个简单的对比:

void and_gate(
    const bool &a_i, 
    const bool &b_i, 
    bool &c_i
) {
    c_i = a_i & b_i;
}

modulevoid 类似,在 verilog / system verilog 语言中为声明一个 模块 的关键字。

模块是一个在硬件描述语言当中非常关键的概念。大到 CPU,小到逻辑门,实际上都能够抽象为一个只有输入和输出接口的黑盒。当你给这些模块对应的输入波形,这些模块会根据输入波形向输出端口输出波形信号。因此,几乎所有硬件描述语言都会将硬件电路抽象为模块来进行代码描述。

在定义好模块的名称之后,我们需要给出这个模块的输入和输出信号。

在 verilog / system verilog 当中,输入和输出定义在 module 的 "参数列表里面,用逗号隔开。对于每个输入输出信号,你需要指定它的方向和类型,我们会在后面详细讲述有关的概念。

之后,就可以在 module 和 endmodule 包起来的模块体(类似于大括号括起来的函数体)部分编写模块的具体逻辑了。我们需要输出 c_o 为 a_i 和 b_i 的与,因此在函数体中编写 c_o = a_i & b_i 这行代码。但是这样还不够。在 verilog / system verilog 中有额外规定:wire 型信号的赋值必须由 assign 引导。因此我们在这个赋值语句之前加上 assign 关键字,就可以完成整个与门模块的设计了。

小结

模块定义:

module <module-name> (
    <input / output list>
);
    <module body>
endmodule

输入输出的 wire 型信号定义:

<input or output> wire <wire-name> // separate by ,

对于 wire 型信号的持续赋值语句:

assign <wire-name> = <expression>;

最后更新: 2023年4月4日
作者:cuibst