Verilog书写模板

一:设计代码书写

1.模块声明部分

  • 目的:模块的起始部分,声明模块名、端口及端口类型。
  • 语法
    verilog
    module <module_name> (<port_list>);
  • 示例:
    verilog
    module my_module(input clk, input reset, output [7:0] data);

2.端口声明

  • 目的声明输入、输出和双向端口的信号类型、宽度等。
  • 语法
    verilog
    input <width> <signal_name>;
    output <width> <signal_name>;
  • 示例:
    input [3:0] addr;
    output reg [7:0] data;

3.内部信号声明

  • 目的模块内部使用的信号声明,包括 regwire 类型。
  • 语法
    verilog
    reg [7:0] signal_name;
    wire [15:0] another_signal;
  • 示例:
    verilog
    reg [7:0] counter;
    wire [3:0] status;

补充:子模块实例化部分

  • 这部分是实例化子模块 uart_byte_tx,并连接到当前模块的信号。
  • 子模块的输入输出与父模块的信号相连接,通过端口映射完成。
  • 示例:
    verilog
     uart_byte_tx uart_byte_tx(
    .Clk(Clk),
    .Reset_n(Reset_n),
    .Data(Data),
    .Send_Go(Send_Go),
    .Baud_set(4),
    .uart_tx(uart_tx),
    .Tx_done(Tx_done)
    );

4.功能逻辑部分

  • 目的:定义模块的具体功能,包括时序逻辑、组合逻辑等。
  • always:用于时序逻辑(如同步电路)。
  • initial:用于仿真时的初始化过程,通常用来设置初始值。
  • 示例:
    verilog
    always @(posedge clk or posedge reset) begin
    if (reset)
    counter <= 8'b0;
    else
    counter <= counter + 1;
    end

5.模块结束部分

  • 目的:标志模块的结束。
  • 语法
    verilog
    endmodule









二、Testbench验证代码书写

Testbench的书写通常由几个关键模块组成,旨在验证设计模块(DUT)的功能。以下是 Testbench的主要模块 及其相关示例:

1. 模块定义与信号声明

这是Testbench的最外层,定义所有的输入、输出信号以及内部信号,确保可以与被测试的设计(DUT)进行连接。

module tb_example;
// 输入信号
reg clk;
reg rst;
reg [7:0] data_in;// 输出信号
wire [7:0] data_out;

// 实例化被测试设计

example_module uut (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_out(data_out)
);

2. 时钟生成

时钟信号是大多数数字系统测试的基础。Testbench需要生成周期性时钟信号,通常使用always块来反转时钟信号

initial begin
clk = 0; // 初始时刻时钟信号为0
end

always #5 clk = ~clk; // 每5单位时间翻转一次,生成10ns周期的时钟

3. 输入激励信号生成(Stimulus Generation)

在Testbench中,输入激励信号用于模拟测试环境中的各种情况。这通常通过initial块完成,模拟不同的输入信号、复位操作、以及模块的状态变化

initial begin
// 初始化信号
rst = 0;
data_in = 8’b00000000;

// 激励信号(模拟输入变化)
#10 rst = 1; // 在10单位时间后解除复位
#5 data_in = 8’hA5; // 5单位时间后输入A5
#10 data_in = 8’hFF; // 10单位时间后输入FF
end0

4. 输出监控与检查(Monitoring & Checking)

Testbench通常需要监控输出信号,以验证设计是否按照预期工作。可以使用$monitor$display等语句输出信号值,并根据输出结果判断设计是否符合预期。

initial begin
// 输出检查
$monitor(“Time = %0t, data_out = %h”, $time, data_out);
end

5. 仿真控制(Simulation Control)

仿真控制模块用于控制仿真何时开始、停止或结束。通常使用$finish$stop来控制仿真进程,以便结束测试或进入交互调试模式。

initial begin
// 等待一段时间后结束仿真
#100;
$finish; // 结束仿真
end

6. 断言(Assertions) (可选)

在Testbench中,可以使用断言来确保信号的值符合预期。这是一种自动化的验证方法,常用于验证时序逻辑或状态机的行为。

// 断言:确保data_out在每个时钟周期都保持正确的值
always @(posedge clk) begin
assert(data_out == expected_value) else $fatal(“Data mismatch at time %0t”, $time);
end

Testbench总结

在一个标准的Testbench中,通常包括以下几个模块:

  1. 模块定义与信号声明:定义Testbench中的信号,包括时钟、复位、输入输出等。
  2. 时钟生成:生成时钟信号,通常通过always块生成周期性的时钟波形。
  3. 输入激励信号生成:通过initial块生成输入信号,模拟系统运行时的各种输入场景。
  4. 输出监控与检查:使用$monitor$display来观察和打印输出信号,检查模块是否按预期工作。
  5. 仿真控制:通过$finish$stop控制仿真流程,确保仿真按预定时间停止或进入调试模式。
  6. 断言(可选):通过断言机制来验证设计的正确性,自动检测不符合预期的行为

通过这些模块,Testbench可以有效地验证被测试模块的功能是否正确,并确保其在不同输入条件下的行为符合预期。

 

留言

您的邮箱地址不会被公开。 必填项已用 * 标注