跳转到内容
GYX / Blog

verilog学习笔记

reg 是最常用的寄存器类型,寄存器类型通常用于对存储单元的描述。

寄存器类型信号的特点是在某种触发机制下分配了一个值,在下一触发机制到来之前保留原值。

reg 类型的变量不一定是存储单元,如在 always 语句中进行描述的必须是用 reg 类型的变量。

定义语法: reg[msb,lsb] reg1,reg2,...,reg N;

没有定义信号数据类型是,缺省为 wire 类型,不是 reg 类型。

在本模块中使用always设计的信号都定义为reg型,其他信号都定义为wire型。

assign 语句是连续赋值语句,一般将一个变量的值不间断的赋值给另一变量,两个变量之间就类似被导线 bond 在一起,习惯上当作连线用。 基本格式: assign a = b (逻辑运算符)c ... 应用范围: 1.连续赋值 2.连线 3.对 wire 型变量赋值,wire 是线网,相当于实际的连接线,如果要用 assign 直接连接,就用 wire 型变量,wire 变量的值随时发生变化。

always 语句是条件循环语句,执行机制是通过对一个称为敏感变量表的时间驱动来实现的。 基本格式:

always @(敏感事件)begin
if(sel == 0)
c = a + b;
else
c = a + d;
end

当敏感事件的条件满足一次,就执行一次“程序语句”。

always @(a or b or d)begin
if(sel == 0)
c = a + b;
else
c = a + d;
end

这个程序的意思是,当信号a/b/d发生变化时,就执行下面语句。

为避免敏感信号遗漏,可以使用‘*’代替敏感信号(不包括 c)。

always @(*)begin
if(sel==0)
c = a + b;
else
c = a + d;
end

这种条件信号变化结果立即变化的always语句被称为“组合逻辑”\textcolor{cyan}{这种条件信号变化结果立即变化的always语句被称为“组合逻辑”}

always @(posedge clk)begin
if(sel==0)
c <= a + b;
else
c <= a + d;
end

上述代码敏感列表是“posedge clk”,其中posedge表示上升沿。当clk由0变成1的瞬间执行一次程序代码,即第2至5行,其他时刻c的值保持不变。

always @(negedge clk)begin
if(sel==0)
c <= a + b;
else
c <= a + d;
end

上述代码的敏感列表是“negedge clk”,其中negedg表示下降沿。当clk由1变成0的瞬间执行一次程序代码,即第2至5行,其他时刻c的值保持不变。

always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
c <= 0;
end
else if(sel==0)
c <= a + b;
else
c <= a + d;
end

上述代码的敏感列表是“posedge clk or negedge rst_n”,当clk由0变成1的瞬间,或者rst_n由1变化0的瞬间,执行一次程序代码,其他时刻c的值保持不变。

这种信号边沿触发,即信号上升沿或下降沿才变化的 always 语句,被称为“时序逻辑”,此时信号clk是时钟,信号rst_n是复位信号。都是只有放在敏感列表并边沿触发。

组合逻辑器件的赋值采用阻塞赋值“=”,时序逻辑器件的赋值语句采用非阻塞赋值“<=”\textcolor{cyan}{组合逻辑器件的赋值采用阻塞赋值“=”,时序逻辑器件的赋值语句采用非阻塞赋值“<=”}

在 Verilog 中的数字表示方式,最常用的格式使:<位宽>‘<基数><数值>,如4'b1011。

  • 位宽:描述常量所含位数的十进制整数,可选项。例如4'b1011中的 4 就是位宽,简单来说就是 4 根线。如果没有这一项可以通过常量的值进行推断。例如'b1011可知位宽是 4,而'b10010可推断出位宽为 5。
  • 基数:表示数值是多少进制。可以是b,B,d,D,o,O,h或者H,分别表示二进制、十进制、八进制和十六进制。\textcolor{cyan}{可以是b,B,d,D,o,O,h或者H,分别表示二进制、十进制、八进制和十六进制。} (默认十进制)。
  • 数值:由基数所决定的表示常量真实值的一串 ASCII 码。如果基数定义为 b或B,数值可以是0,1,x,X,z或Z。
    • x:未知状态(unknown)
    • z:高阻态(high impedance)

在数字电路中如果芯片A给芯片B传递数据,例如传递0或者1信息,可以将芯片A和芯片B 通过一个管脚进行相连,然后由芯片A控制该管脚输出为高电平或者低电平,通过高低电平来表示0 和1。

一个管脚拥有高低电平两种状态,可以分别表示数字0和1的两种情况。如果芯片A要发数字0、1、2、3给芯片B又要如何操作呢? 可以让芯片A和芯片B连接两根管脚,即两条线:a和b。当两条线都为低电平时,表示发送数字0;当 a为高电平b为低电平时,表示发送数字1;当 a为低电平b为高电平时,表示发送数字2;当两条线都是高电平时,表示发送数字3。

也可以一根线表示符号,以此表示正负数。

常用作判断条件,从而告诉综合工具设计者不关心它的电平是多少。

always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout<= 0;
end
else if(din==4'b10x0)begin
dout<= 1;
end
end

表示设计者不驱动这个信号,通常用于三态门接口当中。

“在 FPGA 内部没有必要减少连线,所以使用三态信号是没有意义的。因此,建议各位在进行设计时不要在FPGA内部使用高阻态“z”,因为没有必要给自己添加“思考”的麻烦。”

常用运算符主要有’+’,’-’,’*’。 除法和求余不是简单逻辑门搭建起来的,故不常用,设计师因尽量避免相关运算,以此减少资源消耗和复杂度。

在写代码时,需要注意信号的位宽,最终的结果取决与“=”左边信号的位宽,保存低位,丢弃高位。

  • 正数:保持不变
  • 复数:符号位保持不变,数值按位取反再加1