Verilog语法-模块module[Day2学习笔记]

1概述

Verilog HDL是一种用于数字逻辑电路设计的硬件描述语言,可用来进行数字电路的仿真验证、时序分析、逻辑综合。

  • 用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型。

  • Verilog HDL既是一种行为描述语言,也是一种结构描述语言。

  • 既可以用电路的功能描述,也可以用元器件及其之间的连接来建模。


2模块 Module

模块(module)是Verilog的基本单位,除了编译指令,其他所有的设计代码都必须放在一个或多个模块中。对模块的描述可以是任意的,可以是行为描述、数据流描述或结构描述。

格式:

module <模块名-对应功能>(
    input  <端口>,
    output <端口>
    );
...
<模块内容>
...
endmodule

一个模块内部可以使用其他模块,称为实例。上层模块可以引用底层人意层次模块的变量。

格式:

  1. 信号名关联法(多用)

<实例名rtl>  <第二层实例名>.(变量名-tb)  //.表示索引

b. 位置关联法

//信号名关联法
sort4 sort4_tb(
    .ra(ra),
    .rb(rb),
    .rc(rc),
    .rd(rd),
    .a(a),
    .b(b),
    .c(c),
    .d(d)
);
//位置关联法
sort4 sort4_tb_u(a,b,c,d,ra,rb,rc,rd);

拿二选一举例,子模块为mux2to1,基本单元为u_mux2to1:

  1. 信号名关联法

mux2to1 u_mux2to1(
    .out(u_out),
    .a  (u_a),
    .b  (u_b),
    .sel(u_select)
    );
  1. 位置关联法

mux2to1 u_mux2to1(a,b,sel,out);

3模块总结

  1. Verilog HDL中的标识符可以是任意一组字母、数字、$和下划线_组合,区分大小写。但标识符的第一个字符必须是字母或下划线

  1. Verilog HDL是由模块组成,每个模块嵌套在module与endmodule声明语句之间。模块之间是可以进行层次嵌套的。

  1. 每个Verilog HDL源文件中,只准有一个顶层模块,其他为子模块。

  1. 每个模块要进行端口定义,并说明输入输出端口,然后对模块的功能进行行为逻辑、数据流、结构描述。

  1. 除了endmodule、begin_end、fork_join语句外,每个语句和数据定义后必须有分号

  1. 可用/*...*/和//...进行注释。


4二选一模块举例

以二选一来举例,其电路图如下图所示,

列举了3种方式,Type 1 是hdlbits中的原题,

//多路复用器
//---------------------------Type 1:---------------------------
/* Q:Create a one-bit wide, 2-to-1 multiplexer. 
     When sel=0, choose a. When sel=1, choose b. */
module top_module( 
    input   a, b, sel,
    output  out 
); 
    assign out = (sel) ? b : a ; //sel=1 ,out=b; sel=0, out=a;
    // ***** 信号 = 条件?表达式1:表达式2; *****
endmodule


// ---------------------------Type 2: Mux2to1---------------------------
//Choose one of the two channels of data as the output
module mux2to1(
    input    sel,    //select signial 1:b, 0:a   
    input    op_a,   //
    input    op_b,   //
    output   out     //
    );

reg out_t; //out_t为寄存器,为reg
assign out = out_t;

always @(*) begin   //*——组合逻辑(无触发器)
    if (sel) begin
        out_t = op_b;
    end
    else begin
        out_t = op_a;
    end
end
endmodule


// ---------------------------Type 3---------------------------
module mux2to1(
    input     a     ,
    input     b     ,
    input     s     ,
    output    out
    );
reg out;   //组合逻辑的reg,不是触发器,仅为组合逻辑的信号
           
always @(s or a or b)begin  //* = 敏感信号列表,表内信号变化,会触发always,执行一次列表(所有电平信号)
    if (!s) 
        out = a;
    else 
        out = b;
end
endmodule

5Verilog用于模块的测试

  1. 仿真是什么?为什么进行仿真?

仿真是对电路模块进行动态的全面测试。通过观测被测试信号的输出信号是否符合要求,可用调试和验证逻辑系统的设计和结构准确与否,并发现问题及时修改。

  1. 仿真可以在几层面上进行?每个层面的仿真有什么意义?

仿真有:前(RTL)仿真、逻辑网表仿真、门级仿真和布线仿真

  • 前(RTL)仿真、逻辑网表仿真、门级仿真:可以调试和验证逻辑系统的设计和结构是否准确,并发现问题及时修改;

  • 布线后仿真:分析设计的电路模块的运行是否正常。

  1. 如何检查程序的功能是否正确?

  • 需要有测试激励信号输入到被测模块;

  • 需要记录被测模块的输出信号;

  • 需要把功能和行为描述的Verilog模块转换为门级电路互连的电路结构(综合);

  • 需要对已经转化为门级电路结构的逻辑进行测试(门级电路仿真);

  • 需要对布局布线后的电路结构进行测试(布局布线后仿真)。

在二选一中,

测试信号和测试激励的产生--ain\ bin\ select

被测试模块的测试信号的响应--out

对二选一进行测试:

//always, initial是并行的
// -------------------------1------------------------
module mux2to1_tb();
reg     a        ;  //rtl input
reg     b        ;  //rtl input
reg     select   ;  //rtl input
wire    outw     ;  //rtl output

mux2to1 mux2to1_inst(
    .op_a(a)        ,
    .op_b(b)        ,    
    .sel(select)    ,
    .out(outw)
    );

initial begin  //对输入赋0
    a       = 0 ;        
    b       = 0 ;
    select  = 0 ;
    clk     = 0 ;
end

initial begin  //产生时钟; 每延时5单位,给clk取反
    forever #5 clk = ~clk ; 
end
/* 产生时钟
always #5 clk =~ clk; 
*/

always begin   //always @(posedge clk)begin
    #10 a = {$random}%2 ;
    #5  b = {$random}%2 ;
end

always #20 select = ~select ;

initial begin
   #200 $stop ; 
end 

endmodule

// -------------------------2------------------------
`timescale 1ns/1ps //仿真时间单位/精度

module mux2to1_tb();

reg     ain, bin, select    ;
reg     clk                 ;
wire    outw                ;  //不写默认wire型 

initial begin //0时刻给初值0;initial--只执行一次 
    ain     =  0  ;
    bin     =  0  ;
    select  =  0  ;
    clk     =  0  ;
end 

always #10 clk = ~ clk;  // 产生一个时钟波形
/*
forever begin
    #10 clk = ~ clk ;
end
*/

always @(posedge clk)   // 产生ain, bin随机值
    begin
        #1 ain = ($random)%2 ;  //模2,0/1
        #3 bin = {$random}%2 ;  
    end
end

always #2 select = !select ; //选通信号

initial begin
    #200
    $finish();
end

//例化
mux2to1 mux2to1_inst(.out(outw),.a(ain),.b(bin),.s(select));

endmodule

Q. 若不用initial块,是否能产生测试时钟?

可以。产生测试时钟有两种:

//-----------第一种------------
initial begin              //产生时钟; 每延时5单位,给clk取反
    forever #5 clk = ~clk ; 
end
//-----------第二种------------
always #5 clk =~ clk;         //每延时5单位,给clk取反

以上均为本人学习笔记,若有错误请及时纠正。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值