【自用】Verilog笔记

一、语法

1、模块

module test(A,B,C,D,F1,F2);      // test为模块名

    input A,B,C,D;               // 输入端口,默认为wire类型信号,一般都是wire
    output F1,F2;                // 输出端口,默认wire
    wire F1;                     // 连线
    reg  [2:0] F2;               // 3bit寄存器

endmodule




module  top_module(
    input a,
    input b,
    output out
);

// 模块实例化语法: 模块名 实例名(定义连接port的信号);
	mod_a instance2 (.in1(a), .in2(b), .out(out));    // 即普通函数
 
endmodule




module top_module(input [7:0] in,  output [7:0] out);
    genvar i;        // genvar i; 也可以定义在generate内部
    generate
        for(i = 0; i < 8; i++) begin: bit
             assign out[i]=^in[8-1:i];
        end
    endgenerate
endmodule

2、赋值语句

 对应wire,持续赋值语句

assign F = (A & B) | (A & C);      // F = AB + AC




 对应assign,可用if、case、for

always@(A or B)            // A或B发生变化就执行后面语句
begin
    if(A == B)             // 只能在always块内
      C <= 1;
    else
      C <= 0;

    case(A)                   // 只能在always块内
        2'b00 : B <= 1;       // 2'b表示2位二进制
        2'b01 : B <= 0;
        2'b10 : B <= 1;
        2'b11 : B <= 1;
        default :B <= 0;     // 当A为01时,输出B为0;A为00,10,11时为1
    endcase
end

always@(posedge A)            // 在A的上升沿时执行后面语句
begin
  b <= 1'b1;                  // 1'b表示一位二进制,再例如4’b 1111表示四位二进制数1111
  a <= b;                     // 非阻塞赋值(< =),b先赋值给a,b再变为1
end

always@(negedge B)            // 在B的下降沿时执行后面语句
begin
  b = 1'b1;                   // 阻塞赋值(=),a、b均为1
  a = b;
end

3、逻辑运算

(1)逻辑运算符:&& (与)、==(相等)、||(或)、!=(不等)

        m&&n :判断m和n是否全为真(非0即为真),真则输出1'b1,否则输出1'b0

        最后输出结果只有1bit 

(2)按位运算符:& 、| 、~ 、^ 、~& 、~^ 、~| 

        m&n  : 是把m的每一位与n的每一位按位做与运算(4’b1010 & 4’b0101 = 4’b0000)

        输出结果与m/n的bit数相同

(3)归约运算符:& 、| 、~ 、^ 、& 、~^ 、~| 

        只有一个参量参与运算时(&为一元运算符),表示规约与,即向量内部进行与运算

&a [3:0]      // AND:a[3]&a[2]&a[1]&a[0] 相当于 (a[3:0] == 4'hf)
|b [3:0]      // OR:b[3]|b[2]|b[1]|b[0] 相当于 (b[3:0] != 4'h0)
^c [2:0]      // XOR:c[2]^c[1]^c[0]

        即(&4’b0101 = 0&1&0&1 = 1'b0)
        最后输出结果只有1bit 

(4)其他:

 条件运算符 “ ?:”

assign a = (b==3) ? 4 : 5;      // 如果b=3,那就将4赋值给a,如果不等于就将5赋值给a;




 拼接运算符 “ { , } ”

c = { a , b };      // 假设a=3’b011,b=3’b101,c的结果就为011101

// 但前提是c这个变量的位宽必须要大于6,如果他只有4bit位宽,那结果就变为1101。

二、常量

1、十进制整数 表示 整型常量

        1)正数: 直接写 10 表示位宽为32bit的十进制整数(系统默认)

        2)负数:  -10需要用二进制补码表示,多了一位符号位(1 1010)

        3)用科学计数法表示:12.345e3  表示  12345

2、基数法 表示 整数型常量

        1) 二进制(b):     8'b1000_1100

                当表示二进制时,最好每4位写一个下划线以增强可读性

                当位宽大于二进制位数时左边自动补0,位宽小于二进制数时从左边截断

        2)十六进制(h):  8'h8c

        3)八进制(o):      8'o214

                基数表示法中遇到x时:十六进制表示4个x,八进制中表示3个x

        4)十进制(d):      8'140

3、字符串

       每个字符由1个8位的ASCII码值表示,即需要1byte存储空间

        eg.  “Hello world”  字符串由11个ASCII符号构成,需要11byte存储空间

三、参数

        参数的名称一般为大写,以区分其他变量

1、parameter(常量)

        通常出现在module内部,常被用于定义状态、数据位宽等

        只作用于声明的那个文件,且可以被灵活改变

parameter STATE = 1'b0;

2、localparam(局部参数)

        只在本模块中使用

localparam  STATE= 1'b1’;

四、向量(vector)

        是一组信号的集合,可视为位宽超过1bit  的 wire 信号

1、定义方式

//输入输出型
input [7:0] a, b;        // [upper:lower] 定义位宽,如 [7:0] 表示位宽为8 bit
output reg [7:0] out;
 
// 模块中间向量
wire [7:0] c, e;
reg [7:0] d;

2、向量片选

        eg. 多路选择器:实现一个 256 选 1 选择器,sel 信号作为选择信号

                                    当 sel = 0 时选择 in[3:0],sel = 1 时选择 in[7:4],以此类推

module top_module (
	input [1023:0] in,
	input [7:0] sel,
	output [3:0] out
);

	assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};    // 直接一个个选
 
    // or

	assign out = in[sel*4 +: 4];          // 索引从 sel*4 开始的高4bit信号

    // or

	assign out = in[sel*4+3 -: 4];        // 索引从 sel*4+3 开始的低4bit信号

endmodule

### 关于野火 Verilog 学习笔记与 FPGA 教程 #### 什么是 VerilogVerilog 是一种硬件描述语言 (HDL),用于设计和验证数字电路。它广泛应用于 FPGA 和 ASIC 的开发过程中,能够通过高级抽象来定义复杂的数字逻辑行为。 --- #### WildFire FPGA 系列教程中的 Verilog 学习要点 以下是基于提供的参考资料整理的关键知识点: 1. **组合逻辑的设计** - 组合逻辑的核心概念可以通过多路选择器和译码器实现[^1]。 - 在实际应用中,三八译码器是一个典型的例子,展示了如何利用组合逻辑完成特定功能。 2. **层次化设计的重要性** - 层次化设计是一种有效的模块划分方法,在复杂项目中尤为重要[^2]。 - 主模块通常由 `wire` 类型变量组成,因为它们可以立即响应外部变化。 - 如果子模块需要实时感知输入信号的变化,则其内部连接也应采用 `wire` 类型。 3. **Wire 与 Reg 的区别** - 在 Verilog 中,`wire` 和 `reg` 是两种基本的数据类型,具有不同的用途[^3]。 - 所有在 `always` 或 `initial` 块中被赋值的变量都必须声明为 `reg` 类型。 - 使用 `assign` 语句进行连续赋值时,目标变量必须是 `wire` 类型。 4. **Gitee 资源推荐** - 提供了一个公开的 Gitee 仓库链接,其中包含了丰富的 FPGA 实战案例以及 Verilog 编写指南。 - 地址如下: ```plaintext https://gitee.com/Shaoyang1202/FPGA_Verilog ``` 5. **实践建议** - 对初学者而言,理解并掌握简单的组合逻辑(如加法器、比较器)是非常重要的起点。 - 推荐观看 B 站上的《WildFire FPGA》系列视频课程,尤其是第九讲涉及的内容有助于深入理解层次化设计理念。 --- #### 示例代码:简单组合逻辑实现 以下展示了一段使用 Verilog 描述的二选一多路选择器代码片段: ```verilog module mux_2to1 ( input wire sel, // 控制信号 input wire a, // 输入A input wire b, // 输入B output reg out // 输出端口 ); always @(*) begin if (sel == 1'b1) begin out = b; // 当sel=1时,选择b作为输出 end else begin out = a; // 否则选择a作为输出 end end endmodule ``` 上述代码说明了如何在一个 `always` 块中操作 `reg` 变量,并结合条件判断实现逻辑切换。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值