热度 47| ||
本人是东南的一名电子菜鸡,目前仍在东大读研。此前本科四年东学西学,没有留下学习痕迹。于研0顿悟,开始记录下自己的Verilog学习之旅,目的一是监督自己学习进展;目的二是记录自己学习感悟;目的三是给后来者分享自己经验;目的四是希望各位同仁批评指正本人的不足之处。
本人此前多次尝试想自学Verilog,但多次不得要领。我们大四有门课程设计需要上机,使用的主要语言就是Verilog。但是无奈老师身体欠恙,助教上课。于是乎学风浮躁,虽然最终综评成绩第一,但其实没学到多少真东西。
真正算接触到Verilog是在wqw师兄的带领下,并且强调了Verilog对一个数字硬件工程师的重要性,因此才潜下心来,虚心学习。
首先要对一个Verilog语言的基本框架有认识。
包括:(信号定义);模块名;模块信号声明;模块功能;
module adder(
input clk, //补充
input RESETn, //补充
input [2:0] a,
input [2:0] b,
output reg [4:0] c
);
always@(posedge clk or negedge RESETn)begin //asynchronous reset
if(!RESETn)begin
c <= 'd0;
end
else c <= a + b;
end
endmodule
wire型表示直通,输入有变化,输出立即发生改变,需要持续的驱动;此外,在模块连接时,wire型定义的变量也可以看成一根导线,用于连接不同的模块。wire型变量主要用在连续赋值语句中(例如assign)。
reg型相当于一个存储单元,reg型一定要有触发,不需要有持续的驱动。reg型变量主要用在过程赋值语句中(例如initial,always)。
变量类型 | 变量的物理模型 | 变量用途 | 无驱动时的默认值 |
---|---|---|---|
wire型变量 | 直通,类似一根导线,需要持续驱动 | 主要用于连续赋值语句(如assign) | z |
reg型变量 | 存储,类似寄存器,不需要持续驱动 | 主要用在过程赋值语句(initial,always) | x |
2.1 时序逻辑一般采用非阻塞语句(<= , nonblocking assignment):
[变量] <= [逻辑表达式];
非阻塞的含义就是,在always模块中,本条赋值语句执行过程中,其他赋值语句也可以执行。
那么为什么会时序逻辑一般采用阻塞语句呢?
always@(posedge clk) a = b; always@(posedge clk) b = a;
当有多个always模块同时被激活时,这样的多组阻塞语句就会产生竞争,导致最终结果可能会由于编译器的不同而产生不同的结果。
always@(posedge clk) a <= b; always@(posedge clk) b <= a;
如果多个always采用阻塞赋值,那么赋值行为就不影响,因为a获得的是b在clk打拍之前的值,b获得的是a在clk打拍之前的值。(此时,a、b的赋值都没有发生变化)
2.2 组合逻辑一般采用阻塞语句(= , Blocking assignment):
[变量] = [逻辑表达式];
阻塞的含义就是,在本条语句赋值结束之前,阻塞了当前其他的赋值任务(类似于C语言和matlab顺序执行的操作)。
3.1 同步复位的模块和波形:
从波形中可以分析,同步复位是一种软复位,也就是说复位信号的优先度并没有很高,即使复位信号下拉为0,也需要等待时钟clk打拍才能实现复位功能;
3.2 异步复位的模块和波形:
从波形中可以分析,异步复位是一种硬复位,也就是说复位信号的优先度很高,只要复位信号拉低为0,就能实现复位功能。
修改了一版(第一版搞混了位宽和数组的定义):
在verilog中,可以定义位宽,不同数之间是可以直接进行相加的,可以进位;
如果需要对某些位宽进行操作,就需要在matlab中定义数组,从而对应每位位宽。
在verilog中数值(多位宽)可以直接进行加减,但是在matlab中的数组并不能直接产生进位,因此我是将数组先转换成十进制数,然后再进行加减,最后再转换成数组,方便后续操作。(本人目前的做法,如有同仁有更好的想法,欢迎来分享)