学完语法后的五个练习,按时间排。每节下面是当时的写作日期。
Verilog 运算符 RTL 与测试平台小项目
2024-03-26
运算符运算代码如下

仿真结果:

- 观察波形发现c、d、e的初始值为x不定态
原因:在上文TB中(initial ain= 4‘d0…)只对输入进行了初始化,而并没有对输出值初始化,而输出的初始化一般在例化(RTL)中,后续补充

-
此外仔细观察以上中间段不定态的波形会发现当上升沿来到时,ain和bin取值为0时,中间a和b的值无论如何变化,其在下一个上升沿到来之前输出值保持不定态,这也佐证了以上RTL代码中提到的
always @(psedge clk) //仅上升沿计算c、d、e取值 begin c = a/b; d = a%b; e = a*b; end
总结此次仿真任需解决的问题:
1、输出出现了X不定态
2、想实现在a、b变化的时候c、d、e直接计算出结果
告辞
3.27对于输出出现了X不定态问题的更新:
考虑在RTL中增加复位信号rstn以在时钟信号到达第一个上升沿之前就将“输出信号”复位,在一定程度上减少X不定态持续时间。
实现该功能逻辑核心代码如下:
always @ (posedge clk or negedge rstn)
在TB中对rstn信号设置:
rstn信号从高电平开始,置零触发RTL中negedge下降沿敏感信号,if语句对输出信号置零,然后回到高电平,最后触发pseedge正常运行与电路功能
具体代码截图:
RTL:

TB:

3.28更新
利用VCS特性可完全消除在波形开始时的X不定态
VCS特性:若开始时negedge rstn = 0,则默认会检测到一个下降沿
所以修改TB中的代码在赋值时一开始就将rstn置0,然后置1即可,若中间在任何时候需要再次复位操作,即可在TB中加入对应的时间复位即可,以上操作就叫做异步复位操作
代码:
initial begin
...
rstn = 1'd0;
#3 rstn = 1'd1;
end
BCD 码加法计数器小项目
2024-03-28
模为60的BCD码加法计数器代码:
功能:从data赋值数字开始计数,逢60向count进1

- 只声明 cout和qout为reg型信号:
cout和qout之所以特别声明为reg,是因为它们在逻辑上需要保持或存储一些值,而其他信号仅仅是用于传递即时的状态或信号所以被默认定义为了wire型,无需存储。
-
33行电路会一直检测 qout 和 cin 的值,并实时计算并更新 cout 的值
-
第21行:计数过程中,个位是最先变化的部分。
当个位从1001(即BCD中的9)增加到1010时,就超出了BCD的有效范围,因为BCD的每一位只能表示从0到9的十进制数。这时个位需要被重置到0000
-
15行:rstn是被设计成响应外部事件的信号,异步复位是复位有自己的信号沿,不在时钟沿复位
-
通常在物理情况下电路上电后短时间内拉低rstn信号,系统的状态可以被明确设定为初始状态,之后rstn会被释放(设为高电平),系统开始正常工作。
-
Verilog中的always块是并发执行的(与其他always块相对),但块内部的if-else语句是基于条件选择的顺序执行逻辑。即每次always块被触发时,基于当前的输入和状态,只有一个分支会被选择执行。
TB:

- tb中哪些信号定义为wire型?
在Verilog测试平台(testbench)中,通常会将从被测试的模块(也就是被称为设备待测,Device Under Test,DUT)的输出端口连接的信号声明为wire类型。这是因为测试平台中不需要主动驱动这些信号,只需要从DUT接收值。
- reg类型的信号在测试平台中用于生成刺激信号(或称作测试向量),用于驱动DUT的输入端口。
- 即使在RTL设计文件中已经声明了qout的位宽,也需要在测试平台文件中再次声明它
- 26~32行这部分代码的作用是在仿真开始时设置data信号的初始值,然后在仿真过程中改变这个值,并在一定时间后结束仿真。这是典型的测试平台行为,用来验证设计在不同的输入情况下的响应,以及确保在给定的条件下,设计的行为是正确的
波形图:

循环语句训练:8 bits 乘法器小项目
2024-04-01
一、for循环_8位2进制乘法器
在Verilog代码中,当定义一个乘法器时,乘积的位宽(即可以存储的位数)应该是两个操作数位宽的和。如果你有两个8位的操作数,你可能得到的最大乘积是16位的。

二、for循环_投票表决器
在硬件逻辑中,检查单个位可能比比较整个数字更快或更简单,这就是为什么原始的代码使用sum[2],而不使用sum>=4

三、for循环_8位二进制数中值为1的位进行计数

四、repeat循环_8位2进制乘法器

代码用移位相加实现乘法:repeat循环size次,每次看tempb的最低位tempb[1],为1就把tempa加到outcome上,然后tempa左移一位、tempb右移一位。波形里7×9=63、5×6=30、13×11=143,结果正确。
任务与函数:冒泡排序
2024-04-02
一、任务与函数的区别:

二、4个4位二进制输入数据的冒泡排序_task

三、对一个8位二进制数中为0的位进行计数_function
- 与投票计数同理

Verilog 饮料机有限状态机
2024-04-06
自动售饮料机-分析输入输出端口信号
输入信号: clk,rst; 输入信号:操作开始: op_start;//定义1开始操作 输入信号: 投币币值: coin_val;//定义2’b01表示0.5元; 2’b10表示1元 输入信号:取消操作指示 : cancel_flag;//定义1为取消操作 输出信号:机器是否占用: hold_ind;//定义0为不占用,可以使用 输出信号:取饮料信号: drinktk_ind;//定义1为取饮料 输出信号:找零与退币标志信号: charge_ind; //定义1为找零 输出信号:找零与退币币值:charge_val;//定义3’b001表示找0.5元;3’b010表示找1元;3’b011表示找1.5元; 3’b100表示找2.0元
状态转移图:

说明: 1.在S0状态下,如果检测到op_start=1,开始检测是否有投币,如果有,一次新 的 售货操作开始; 2.在状态S1/S2/S3/S4下,如果检测到cancel_flag=1,则取消操作,状态返回S0,并 退回相应的币值; 3.在状态S5下,卖出饮料不找零;在状态S6下,卖出饮料并找零; 4.在状态S5和S6 操作完后,都返回状态S0,等待下一轮新的操作开始; 5.只有在S0 状态下,hold_ind=0,可以发起新一轮操作,其它状态下都为1;
rtl

tb:

波形图:

波形依次是tb里的三次操作(波形里的drink_ind、hold即正文的drinktk_ind、hold_ind)。第一次连投三个1元(coin_val=10),drink_ind和charge_ind一起拉高,charge_val=001,即出饮料并找零0.5元;第二次投0.5、1、1元,只有drink_ind拉高,不找零;第三次投0.5、1元后拉高cancel_flag,charge_ind只出现一个很窄的退币脉冲,hold随后回到0。
Discussion
Loading comments…
Checking sign-in…