Verilog HDL学习

翻译自:https://hdlbits.01xz.net

Designing a circuit requires several steps: Writing HDL (Verilog) code, compiling the code to produce a circuit, then simulating the circuit and fixing bugs.

设计电路的步骤:

  1. 写HDL(Verilog)代码;
  2. 编译代码生成一个电路;
    1. Altera Quartus
    2. 逻辑综合,Logic Synthesis
  3. 模拟电路 Simulation;
    1. ModelSim
  4. 修复bug;

Basic

线网(wire): 一输入和一输出的模块(module)

Verilog 内的线网(wire)和其他信号是 有方向的(directional),信息流仅有一个方向,从源到汇(from source to the sinks),source 也经常被称作 driver:驱动一个值到一个wire上。连接组件

请添加图片描述

模块的端口也有方向(通常为输入和输出),输入端口由模块外部的一些东西驱动,而输出端口驱动外部的一些东西。从模块内部的角度来看,输入端口是一个driver或者源,而输出端口是一个汇

Verilog内 assign 是“持续赋值”,驱动右端信号的值到左端的wire上。

持续赋值的意思是 赋值是一直持续的,即使右端的值改变(左端的值会随着右端的值改变而改变),每当任何一个输入改变,输出被重新计算(recompute)

多个assign语句在代码会的顺序是没有关系的;

assign 语句描述/创建 things 间的连接(connection),不是从一个thing到另一个thing的拷贝值的动作

Vectors

Vector 使用一个名字将相关的信号组合在一起,以更方便操作;例如,wire [7:0] w,声明了一个8比特的w,功能上等价于8个独立的 wire

在声明的时候,vector 的维度放在变量名的前面,而 part select 的时候将为度放在向量名的后面

wire [99:0] my_vector;      // Declare a 100-element vector
assign out = my_vector[10]; // Part-select one bit out of the vector

vector的声明:

type [upper:lower] vector_name;

在 Verilog 里,一旦一个 vector 被声明成一种特定的字节序,它必须总是写相同的字节序

e.g., writing vec[0:3]when vec is declared wire [3:0] vec; is illegal.

注:vector的字节序

小端模式:least significant bit 有 更低的index e.g., [3:0]

大端模式:least significant bit 有 更高的index e.g., [0:3]

Implicit nets

在 Verilog 里,net-type信号可以被 assign 语句隐式地创建; 或者 将为定义的一些东西连接到模块端口上时,会创建隐式地 net-type 信号

隐式 net 总是 1 比特的 wire,如果你本意是想使用 vector 时会产生 bug

使用 default_nettype none directive可以disable创建隐式net

wire [2:0] a, c;   // Two vectors
assign a = 3'b101;  // a = 101
assign b = a;       // b =   1  implicitly-created wire
assign c = b;       // c = 001  <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.                             // This could be a bug if the port was intended to be a vector.

Unpacked vs. Packed Arrays

声明的时候vector的索引被写在名字的前面,这些比特被 pack 在一起形成一个 blob;

unpacked 的维度被声明在名字的后面。通常被用于声明memory数组

reg [7:0] mem [255:0];   // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
reg mem2 [28:0];         // 29 unpacked elements, each of which is a 1-bit reg.

访问整个 vector 使用 vector 的名字

assign w = a;

当左右两边的位宽不匹配时,进行0扩展或者截断处理

部分选择操作符

访问vector的一部分

w[3:0]      // Only the lower 4 bits of w
x[1]        // The lowest bit of x
x[1:1]      // ...also the lowest bit of x
z[-1:-2]    // Two lowest bits of z
b[3:0]      // Illegal. Vector part-select must **match the direction of the declaration.**
b[0:3]      // The *upper* 4 bits of b.
assign w[3:0] = b[0:3];    // Assign upper 4 bits of b to lower 4 bits of w. w[3]=b[0], w[2]=b[1], etc.

按位操作符

按位与(&)、按位或(|)、按位非(~)、按位同或(~^)、按位异或(^)

按位操作符对 2 个操作数的每 1bit 数据进行按位操作。
如果 2 个操作数位宽不相等,则用 0 向左扩展补充较短的操作数
取反操作符只有一个操作数,它对操作数的每 1bit 数据进行取反操作。

归约操作符

归约操作符包括:归约与(&),归约与非(~&),归约或(|),归约或非(~|),归约异或(^),归约同或(~^)。

归约操作符只有一个操作数,它对向量操作数逐位进行操作,最终产生一个 1bit 结果

拼接操作符

通过拼接更小规模的向量得到更大的向量;

{3'b111, 3'b000} => 6'b111000
{1'b1, 1'b0, 3'b101} => 5'b10101
{4'ha, 4'd10} => 8'b10101010     // 4'ha and 4'd10 are both 4'b1010 in binary

注意⚠️:

拼接需要知道每个组件的宽度(否则怎么知道结果的长度?);

因此,{1, 2, 3} 是不合法的,会导致错误信息:unsized constants are not allowed in concatenations

拼接操作符可以被用在 赋值符号 的两边;

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值