Verilog语法(1)

之前记录的Verilog语法规则在电脑系统崩掉之后重装时全部丢失了,所以这里重新记录一下Verilog的基础语法以及在实战中的一些运用方法。

1. 电路设计的语法

1.1 设计不使用的语法

  • initial:设计时不使用,仿真时使用
  • task/function:设计时不使用,仿真时很少用
  • for/while/repeat/forever:设计不用,仿真很少用
  • integer:设计不用
  • 模块内部不能有X态、Z态,内部不能有三态接口
  • casex/casez:设计和仿真都不用
  • force/wait/fork:设计不用,仿真很少用
  • #5:延时语句,设计不用,仿真常用

1.2 设计时使用的语法

  • reg/wire、parameter:定义参数的语法
  • assign、always:很常用的语法
  • 一般只用if elsecase 两种条件语句
  • +、-、*、/、%:算术运算符可以使用
  • =,<=:赋值运算符,时序逻辑用<=,组合逻辑用=
  • 关系运算符:>,<,>=,<=
  • 逻辑运算符:&&,||,!
  • 位运算符:~,|,^,&
  • 移位运算符:<<,>>
  • 拼接运算符:{}

2. 电路设计的结构

  • 组合逻辑:

    1
    2
    3
    always @ (*) begin
    expression
    end
  • 同步复位时序逻辑

    1
    2
    3
    4
    5
    6
    7
    always @ (posedge clk) begin
    if(rst_n == 1'b0) begin
    expression
    else begin
    expression
    end
    end
  • 异步复位时序逻辑

    1
    2
    3
    4
    5
    6
    7
    always @ (posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
    expression
    else begin
    expression
    end
    end

3. 电路设计要点

  • 一个always 只产生一个信号:设计清晰简洁方便调试
  • 一个信号只在一个always中产生
  • always 模块要考虑到全部的情况
  • 条件判断只用if else或者case
  • 含有posedge或者negedge的一定是时序电路
  • 即改即用使用组合逻辑,延时改变使用时序逻辑

4.模块例化

例化可以简单理解为编程语言中的函数功能(但是实际上并不一样),当有一个模块被例化两次之后,这两个模块都占有实际的电路结构,虽然这两个功能都有相同的功能,并不会共用一套电路,编程语言中的函数是随用随分配,这是例化和函数的一个区别

  • 例化的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //设计模块
    module uart(
    clk,
    rst_n,
    vld_in,
    data_in,
    uart_out,
    uart_in,
    vld_out,
    data_out,
    rdy_in
    );

    //例化方法:
    uart u1( //例化的模块名,实例的模块名
    .clk(clk_100M),
    .rst_n(sys_rst_n),
    .vld_in(bt_data_out_vld),
    .data_in(bt_data_out),
    .uart_out(uart_tx),
    .uart_in(uart_rx),
    .vld_out(uart_data_out_vld),
    .data_out(uart_data_out),
    .rdy_in(uart_in_rdy)
    );
  • 参数的例化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    //设计模块
    module uart(
    clk,
    rst_n,
    vld_in,
    data_in,
    uart_out,
    uart_in,
    vld_out,
    data_out,
    rdy_in
    );
    parameter DATA_W = 8;


    //例化方法:
    uart#(.DATA_W(16)) u1( //例化的模块名,实例的模块名,这里将模块的8位位宽改成了16位的位宽
    .clk(clk_100M),
    .rst_n(sys_rst_n),
    .vld_in(bt_data_out_vld),
    .data_in(bt_data_out),
    .uart_out(uart_tx),
    .uart_in(uart_rx),
    .vld_out(uart_data_out_vld),
    .data_out(uart_data_out),
    .rdy_in(uart_in_rdy)
    );

5. 运算符

5.1 信号类型reg/wire

  • 设计代码仅用regwire
  • 由本模块且是由always产生的信号,都用reg
  • 测试代码中,用initial产生的信号(一般是对测模块的输入),用reg类型
  • 其他的都用wire
  • reg类型的信号,也不一定是产生寄存器的(比如组合逻辑中的一些信号,也是由always产生的,也是用reg,但是这里没有寄存器)

5.2 参数parameter

1
parameter CNT = 12;

可以简单理解为C语言中的宏定义,例如上述代码的作用就是将整个模块中的CNT全部替换成12

5.3 算术运算符

  • +、-、*、/、%:一般除法和取余比较少于,因为它们涉及到的逻辑比较复杂

5.4 关系运算符

>=,<=,==,>,<:一般用于条件判断

5.5 赋值运算符

  • >=:时序逻辑里使用
  • =:组合逻辑里使用

5.6 逻辑运算符

  • &&:与
  • ||:或
  • !:非
  • 一般来说两边都是1bit,多用于条件判断

5.7 位运算符

  • &:按位与
  • |:按位或
  • ~:按位取反
  • ^:按位异或
  • 一般来说用于赋值运算

5.8 移位运算符

  • >>:右移
  • <<:左移
  • 一般用于乘除运算

5.9 拼接运算符

  • {}:将不同bit的数拼接在一起
  • {3{a[0]}}:表示a[0]a[0]a[0]
  • © 2019-2022 Wendell
  • Powered by Hexo Theme Ayer

请我喝杯咖啡吧~

支付宝
微信