Verilog 回顾

一些语法

模块的结构:

 
            
                module [design_name] ( [port_list] );
                
                [list_of_input_ports]
                [list_of_output_ports]
                
                [declaration_of_other_signals]
                
                [other_module_instantiations_if_required]
                
                [behavioral_code_for_this_module]
                endmodule
            
        

Architecture Level 负责把系统按功能划分为高层模块并定义接口, RTL Level 则用 Verilog/VHDL 等硬件描述语言精确实现每个模块的具体功能(在此阶段,诸如电路图、技术库之类的低层实现细节则被忽略。例如,一个控制器模块会由多个 Verilog 文件构成,每个文件分别描述该控制器模块中的某个功能模块。)。

wire 和 reg 的类型:

            
                wire xxxx
                reg [xxx:1] xxxx
            
        
数字形式:
            16 // Number 16 in decimal (default)
            0x10 // Number 16 in hexadecimal (C-style notation - NOT standard Verilog)
            10000 // Number 16 in binary (but Verilog treats this as decimal 10000!)
            20 // Number 16 in octal (but Verilog treats this as decimal 20!)
        
数字大小/数值范围:
            [size]'[base_format][number]
            
            // Where:
            // size - Number of bits (decimal only)
            // base_format - 'b (binary), 'd (decimal), 'h (hex), 'o (octal)
            // number - The value in the specified base
        

模块实现示例:

            
                // Module called "dff" has 3 inputs and 1 output port
                module dff ( input d, // Data input
                    input clk, // Clock signal
                    input rstn, // Active-low synchronous reset
                    output reg q); // Registered output (must be 'reg' for sequential logic)
                    
                    // Sequential logic block: executes on every positive clock edge
                    always @ (posedge clk) begin
                    if (!rstn) // Reset condition (active-low: rstn=0 triggers reset)
                    q <= 0; // Non-blocking assignment: reset output to 0 else q <=d; // Non-blocking assignment: capture input data end
                endmodule
            
        
模块实例化示例:
            
                // Instantiate the dff module
                dff my_dff (
                    .d(data_input), // Connect 'd' port to 'data_input' signal
                    .clk(clock_signal), // Connect 'clk' port to 'clock_signal'
                    .rstn(reset_signal), // Connect 'rstn' port to 'reset_signal'
                    .q(output_q) // Connect 'q' port to 'output_q' signal
                );
            
        

            阻塞赋值 = 和非阻塞赋值 <=
            testbench 中使用 =
            rtl 中使用 <=
        
            
                initial begin
                a = 0;
                b = 0;
                #10 a = 1;
                end
            

            
                always @(posedge clk) begin
                q <= d; end
            
        

仿真

输入信号通常声明为 reg,输出信号通常声明为 wire
timescale 用于定义仿真的时间单位和时间精度。

            
                `timescale 1ns / 1ps
            
        
testbench
            
                module tb_top;
                
                endmodule
            
        
initial 块只在仿真开始时执行一次,常用于初始化信号和施加测试激励。
            
                initial begin
                    a = 0;
                    b = 0;
                    
                    #10 a = 1;
                    #10 b = 1;
                    #10 a = 0;
                end
            
        
always 产生时钟
            
                reg clk;
                
                initial begin
                clk = 0;
                end
                
                always #5 clk = ~clk;
        
复位信号
            
                reg rst_n;
                
                initial begin
                rst_n = 0;
                #20;
                rst_n = 1;
                end
            
        
延时
            
                #10;
                a = 1;
                #20;
                a = 0;
            
        
wait 等待某条件成立
            
                initial begin
                    start = 1;
                    #10 start = 0;
                    
                    wait(done == 1);
                    
                    #10;
                    $finish;
                end
            
        
@(posedge clk) 和 @(negedge clk) 等待时钟边沿。
            
                initial begin
                    rst_n = 0;
                    start = 0;
                    data_in = 0;
                    
                    repeat(5) @(posedge clk);
                    rst_n = 1;
                    
                    @(posedge clk);
                    start = 1;
                    
                    @(posedge clk);
                    start = 0;
                end
            
        
$display 打印仿真信息。
            
                initial begin
                a = 0; b = 0; #10;
                $display("a=%b b=%b y=%b", a, b, y);
                
                a = 1; b = 0; #10;
                $display("a=%b b=%b y=%b", a, b, y);
                
                a = 1; b = 1; #10;
                $display("a=%b b=%b y=%b", a, b, y);
                end
            
        
$monitor 只要变量变化,就自动打印。
            
                initial begin
                    $monitor("time=%t a=%b b=%b y=%b", $time, a, b, y);
                end
            
        
$finish 结束仿真。 $stop 暂停仿真,不完全结束。

一个完整的 testbench 示例:

            
                `timescale 1ns / 1ps
                
                module tb_counter;
                
                reg clk;
                reg rst_n;
                reg en;
                wire [3:0] count;
                
                counter uut (
                .clk(clk),
                .rst_n(rst_n),
                .en(en),
                .count(count)
                );
                
                // clock: 100MHz
                initial begin
                clk = 0;
                end
                
                always #5 clk = ~clk;
                
                // stimulus
                initial begin
                rst_n = 0;
                en = 0;
                
                repeat(5) @(posedge clk);
                rst_n = 1;
                
                repeat(2) @(posedge clk);
                en = 1;
                
                repeat(10) @(posedge clk);
                en = 0;
                
                repeat(5) @(posedge clk);
                
                $finish;
                end
                
                // print
                initial begin
                $monitor("time=%t rst_n=%b en=%b count=%d",
                $time, rst_n, en, count);
                end
                
                endmodule