FPGA基础之基础语法
一、基本模块结构
Verilog 代码以 模块(Module) 为单位,每个模块对应一个硬件功能单元(如逻辑门、寄存器等)。
基本格式:
module 模块名 (// 输入输出端口声明input 端口1,input 端口2,output 端口3
);// 内部信号或变量声明wire 信号1;reg 信号2;// 逻辑描述(组合逻辑或时序逻辑)assign 信号1 = 端口1 & 端口2; // 组合逻辑always @(posedge clk) begin // 时序逻辑信号2 <= 端口1;endendmodule
二、端口声明
- 输入端口:
input
- 输出端口:
output
- 双向端口:
inout
示例:
module example (input a, // 单比特输入input [7:0] b, // 8位宽输入output c // 单比特输出
);
三、数据类型
-
线网类型(Net):表示电路中的物理连接(如导线),常用
wire
。wire data; // 单比特线网 wire [3:0] bus; // 4位宽总线
-
寄存器类型(Register):表示存储单元,常用
reg
。reg counter; // 单比特寄存器 reg [31:0] data; // 32位宽寄存器
-
其他类型:
integer
:整数类型(仿真用)。parameter
:常量参数(类似宏定义)。real
:浮点数(仿真用)。
四、基本语法
1. 赋值语句
-
连续赋值(组合逻辑):用
assign
关键字。assign out = a & b; // 与门逻辑
-
过程赋值(时序逻辑):在
always
块中使用。always @(posedge clk) beginq <= d; // D触发器,非阻塞赋值 end
2. 条件语句
-
if-else
:always @(*) beginif (sel == 1'b0)out = a;elseout = b; end
-
case
:always @(*) begincase (sel)2'b00: out = a;2'b01: out = b;default: out = 0;endcase end
3. 循环语句
-
for
循环:integer i; always @(*) beginfor (i=0; i<4; i=i+1)out[i] = a[i] & b[i]; end
-
while
和repeat
(较少用,多用于仿真)。
五、命名规则
- 合法字符:字母、数字、下划线
_
,区分大小写。 - 首字符:必须是字母或下划线(不能是数字)。
- 保留字:不可使用 Verilog 关键字(如
module
,input
,always
)。 - 命名建议:
- 使用有意义的名字(如
clk
,reset
,data_in
)。 - 总线命名:
data[7:0]
表示 8 位数据。 - 避免混淆:如
l
(小写 L)和1
(数字 1)。
- 使用有意义的名字(如
示例:
reg [3:0] counter; // 合法
wire _enable; // 合法
reg 4bit_data; // 非法(首字符是数字)
六、注释
- 单行注释:
//
- 多行注释:
/* ... */
// 这是单行注释
/*
这是
多行注释
*/
七、示例代码
1. 与门模块
module and_gate (input a,input b,output c
);assign c = a & b;
endmodule
2. D 触发器
module d_flipflop (input clk,input reset,input d,output reg q
);always @(posedge clk or posedge reset) beginif (reset)q <= 1'b0; // 复位时清零elseq <= d; // 时钟上升沿采样end
endmodule
八、测试模块(Testbench)
用于验证设计功能的仿真代码:
module testbench;reg a, b;wire c;// 实例化被测试模块and_gate u1 (.a(a), .b(b), .c(c));initial begina = 0; b = 0;#10 a = 1;#10 b = 1;#10 $finish;end
endmodule
九、注意事项
- 阻塞赋值(
=
) vs 非阻塞赋值(<=
):- 组合逻辑用阻塞赋值(
=
)。 - 时序逻辑用非阻塞赋值(
<=
)。
- 组合逻辑用阻塞赋值(
- 敏感列表:
always @(*)
用于组合逻辑,always @(posedge clk)
用于时序逻辑。 - 避免锁存器:组合逻辑中需覆盖所有条件分支(如
if-else
必须有else
)。