HDLBits:在线学习Verilog(七 · Problem 30-34)
本系列内容来自于知乎专栏,链接如下:https://zhuanlan.zhihu.com/c_1131528588117385216
本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同学,都能从中有所收获。
Problem 30: If statement(Always if)
if语句通常对应一个二选一多路复用器,如果条件为真,则选择其中一个输入作为输出;反之如果条件为假,则选择另一个输入所谓输出。if语句必须在过程块内使用。
下面给出了一个基本的if语句和其综合出来的电路。
always @(*) beginif (condition) beginout = x;endelse beginout = y;end
end
这与下面使用条件运算符连续赋值的语句是等价的:
assign out = (condition) ? x : y;
但是,过程if语句使用不当可能会引入新的错误,只有out在所有的条件下都被赋值才会生成正确的组合电路,具体的错误下一个训练才会讲到,
牛刀小试
构建一个可以在a和b之间选择的二选一多路复用器。如果sel_b1和sel_b2都为真,输出b,其他情况输出a。请使用两种方法作答,一次使用assign赋值,一次使用if语句。
解答与分析
// synthesis verilog_input_version verilog_2001
module top_module(input a,input b,input sel_b1,input sel_b2,output wire out_assign,output reg out_always);assign out_assign = sel_b1? sel_b2? b:a :a;always@(*)if(sel_b1&sel_b2)out_always = b;elseout_always = a;endmodule
Problem 31: If statement latches(Always if2)
常见的错误来源:如何避免引入锁存器
在设计电路时,必须首先具体考虑电路:
1、我想实现一个逻辑门;
2、我想实现一个具有输入并产生输出的组合逻辑块;
3、我想实现一组组合逻辑,紧接着一组触发器。
不要上来就写代码,这样往往与你想象的电路相差很远。
if (cpu_overheated) then shut_off_computer = 1;
if (~arrived) then keep_driving = ~gas_tank_empty;
除了你指定的情况以外,会发生些什么,答案是什么也不会发生,输出保持不变。而这往往就导致了电路的错误,所以说语法正确的代码不一定能产生合理的电路(组合逻辑+触发器)。
输出保持不变,这就意味着电路需要记住当前状态,从而产生锁存器。组合逻辑(比如逻辑门)不能记住任何状态。
Warning (10240): ... inferring latch(es)
上述这类警告通常情况下代表错误,除非锁存器是故意生成的。组合电路输出必须在所有输入的情况下都有值。这意味着必须需要else子句或着输出默认值。
牛刀小试
示例:以下代码包含生成锁存器的错误,请勿模仿!!!修复错误,只有当它真的过热时才关闭计算机,真的到达目的地或者需要加油时,才停止驾驶。
always @(*) beginif (cpu_overheated)shut_off_computer = 1;
endalways @(*) beginif (~arrived)keep_driving = ~gas_tank_empty;
end
解答与分析
// synthesis verilog_input_version verilog_2001
module top_module (input cpu_overheated,output reg shut_off_computer,input arrived,input gas_tank_empty,output reg keep_driving ); //always @(*) beginif (cpu_overheated)shut_off_computer = 1;elseshut_off_computer = 0;endalways @(*) beginif (~arrived)keep_driving = ~gas_tank_empty;elsekeep_driving = ~arrived;endendmodule
Problem 32: Casestatement(Always case)
Verilog中的case语句几乎等同于if-else if-else序列,它将一个表达式与其他表达式列表进行比较。它的语法和功能与C语言中的switch语句稍有不同:
always @(*) begin // This is a combinational circuitcase (in)1'b1: begin out = 1'b1; // begin-end if >1 statementend1'b0: out = 1'b0;default: out = 1'bx;endcase
end
1、case语句以case开头,每个case项以冒号结束。而switch语句没有。
2、每个case项只执行一个语句。这样就不需要C语言中break来跳出switch。但这也意味着如果您需要多个语句,则必须使用begin ... end。
3、case项允许重复和部分重叠,执行程序匹配到的第一个,而C语言不允许重复的case项目。
牛刀小试
如果存在大量的case项,则case语句比if语句更方便。因此,在本练习中,创建一个6选1的多路复用器。当sel介于0和5之间时,选择相应的数据输入。其他情况输出0。数据输入和输出均为4位宽。
注意:不要生成锁存器(详见:Problem 31: If statement latches(Always if2))。
解答与分析
// synthesis verilog_input_version verilog_2001
module top_module (input [2:0] sel,input [3:0] data0,input [3:0] data1,input [3:0] data2,input [3:0] data3,input [3:0] data4,input [3:0] data5,output reg [3:0] out );//always@(*) begin // This is a combinational circuitcase(sel)3'b000: out = data0;3'b001: out = data1;3'b010: out = data2;3'b011: out = data3;3'b100: out = data4;3'b101: out = data5;default: out = 4'b0000;endcaseendendmodule
注意这里一定要用default声明一下不在case项里的输出,否则会生成不必要的寄存器,影响电路的功能。
Problem 33: Priority encoder(Always case2)
优先编码器是组合电路,当给定输入时,输出输入向量中的右边第一个1的位置。例如,输入8'b10010000的,则优先编码器将输出3'd4,因为位[4]是从右数第一个1。
牛刀小试
构建一个4位优先编码器。如果没有输入均为零,则输出零。请注意,4位数字有16种输入发的可能。
小提示:使用十六进制(4'hb)或十进制(4'd11)与二进制(4'b1011)相比可以节省打字量。
解答与分析
这是二进制编码的写法,看起来相对直观一点。
// synthesis verilog_input_version verilog_2001
module top_module (input [3:0] in,output reg [1:0] pos);always@(*)case(in)4'b0000: pos = 2'b00;4'b0001: pos = 2'b00;4'b0010: pos = 2'b01;4'b0011: pos = 2'b00;4'b0100: pos = 2'b10;4'b0101: pos = 2'b00;4'b0110: pos = 2'b01;4'b0111: pos = 2'b00;4'b1000: pos = 2'b11;4'b1001: pos = 2'b00;4'b1010: pos = 2'b01;4'b1011: pos = 2'b00;4'b1100: pos = 2'b10;4'b1101: pos = 2'b00;4'b1110: pos = 2'b01;4'b1111: pos = 2'b00;default: pos = 2'b00;endcaseendmodule
作者提供了16进制的编码的写法,他觉得这样打字打的少,2333333。
module top_module (input [3:0] in,output reg [1:0] pos
);always @(*) begin // Combinational always blockcase (in)4'h0: pos = 2'h0; // I like hexadecimal because it saves typing.4'h1: pos = 2'h0;4'h2: pos = 2'h1;4'h3: pos = 2'h0;4'h4: pos = 2'h2;4'h5: pos = 2'h0;4'h6: pos = 2'h1;4'h7: pos = 2'h0;4'h8: pos = 2'h3;4'h9: pos = 2'h0;4'ha: pos = 2'h1;4'hb: pos = 2'h0;4'hc: pos = 2'h2;4'hd: pos = 2'h0;4'he: pos = 2'h1;4'hf: pos = 2'h0;default: pos = 2'b0; // Default case is not strictly necessary because all 16 combinations are covered.endcaseendendmodule
当然,有更简单的写法,那就看下一题吧。
不过还是先谈谈优先译码器,可能在学数字电路的时候优先译码器是左边第一个为0的数字,在本题中是右面第一个。两者都可以叫做优先译码器,出现的第一个数字把后面的数字屏蔽掉了,第一个数字具有较高的优先级,所以叫做优先译码器。
与优先译码器相对应的简单译码器,简单译码器的输入要求只能有一个1。出现多个1的时候视不同情况有不同的处理方式。
Problem 34: Priority encoder with casez(Always casez)
牛刀小试
构建一个8输入的优先编码器。给定一个8位向量,输出输入向量中左数第一个1的位置。如果输入均为0,则输出零。例如,输入8'b10010000应该输出3'd4,因为位[4]是第一个出现1的位置。
如果还按上一个练习(Problem 33: Priority encoder(Always case2))写case语句的话,case语句中将有256个case项。如果case语句中的case项与某些输入无关,就可以减少列出的case项(在本题中减少到9个)。这就是casez的用途:它在比较中将具有值z的位视为无关项(即输入01都会匹配到)。
例如:下面的代码就是上一个联系中的4输入优先编码器:
always @(*) begincasez (in[3:0])4'bzzz1: out = 0; // in[3:1]输入什么都可以4'bzz1z: out = 1;4'bz1zz: out = 2;4'b1zzz: out = 3;default: out = 0;endcase
end
case项是按顺序检查的(实际上,它更像是生成一个巨大的真值表然后生成超大的门)。注意有输入(例如,4'b1111)匹配多个case项。选择第一个匹配(因此4'b1111匹配第一个case项,out = 0)。
还有一个类似的casex,将输入的x和z都视为无关。不认为casex比casez有什么特别的好处。(作者个人感觉没必要用casex,z和x状态的问题涉及电路的基本知识)
符号"?" 是z的同义词,所以2'bz0与2'b?0相同。
解答与分析
// synthesis verilog_input_version verilog_2001
module top_module (input [7:0] in,output reg [2:0] pos);always @(*)casez (in)8'bzzzzzzz1: pos = 0;8'bzzzzzz1z: pos = 1;8'bzzzzz1zz: pos = 2;8'bzzzz1zzz: pos = 3;8'bzzz1zzzz: pos = 4;8'bzz1zzzzz: pos = 5;8'bz1zzzzzz: pos = 6;8'b1zzzzzzz: pos = 7;default: pos = 0;endcaseendmodule
嗯,用casez就方便多了。。。
原文作者:ljgibbs
原文地址:https://zhuanlan.zhihu.com/p/58315855
本公众号授权发布
【打个广告】
各位对数字IC和FPGA设计感兴趣的盆友们,我们搭建了一个QQ交流群。经过这一段时间的发展,群聊中已经有将近800个志同道合的同学加入。QQ群里已经整理了许多的资料,其中包含有视频,资料,教程,芯片手册,软件安装包,虚拟机环境。覆盖了从FPGA开发,数字前端,电路设计等等一系列的内容。QQ群号为:810689010 ,进群暗号:公众号。欢迎进群交流!
为了能让这个群长期发展下去,用于支付扩建群聊所需的会员费,无奈将这个群设置成付费入群,仅需一元即可,多谢大家支持。
QQ群二维码
期待与您的添加!
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
长按识别图中二维码关注
欢迎关注微信公众号【数字积木】,更精彩的内容等着你!
HDLBits:在线学习Verilog(七 · Problem 30-34)相关推荐
- HDLBits: 在线学习 SystemVerilog(五)-Problem 19-23
HDLBits: 在线学习 SystemVerilog(五)-Problem 19-23 HDLBits 是一组小型电路设计习题集,使用 Verilog/SystemVerilog 硬件描述语言 (H ...
- verilog for循环_HDLBits:在线学习 Verilog (二十四 · Problem 115-119)
本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同 ...
- 4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)
本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同 ...
- verilog 简单module_HDLBits:在线学习 Verilog (二十九 · Problem 140-144)
本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同 ...
- verilog 计数器_HDLBits: 在线学习 Verilog ()
本系列文章将向大家推荐一个学习 Verilog 的好去处:HDLBits. HDLBits 在提供 Verilog 基础语法教程的同时,还能够在线仿真你的 Verilog 模块,将你的输出与正确的时序 ...
- HDLBits: 在线学习 SystemVerilog(十七)-Problem 106-114(移位寄存器)
HDLBits 是一组小型电路设计习题集,使用 Verilog/SystemVerilog 硬件描述语言 (HDL) 练习数字硬件设计~ 网址如下: https://hdlbits.01xz.net/ ...
- verilog异步复位jk触发器_HDLBits: 在线学习Verilog(Problem 120-126)
这几天在刷HDLBits,参考的是HDLBits中文导学专栏:HDLBits中文导学,刷到120题的时候发现缺少了中间的120题到126题的解析,就打算自己边写边记录一下.也方便其他的同学进行参考. ...
- verilog学习 | HDLBits:在线学习答案
HDLBits 在提供 Verilog 基础语法教程的同时,还能够在线仿真 Verilog 模块. 以下是各单元解法答案.希望可以帮助您了解 Verilog 的工作原理. 前言 HDLBits 在提供 ...
- 【日常分享】多邻国v4.93.4,在线学习英语、日语、韩语、德语…等30多种语言
多邻国v4.93.4,在线学习英语.日语.韩语.德语-等30多种语言. 国外的一个大佬破解的,所有功能已全部免费. 下载: https://wws.lanzous.com/iX5l3k8ajgd 密码 ...
最新文章
- 已经入门了C++,后面的路怎么走?
- Elasticsearch创建索引和映射结构详解
- XP与Ubuntu双系统的问题
- boost::intrusive::splay_set用法的测试程序
- 深度学习(12)TensorFlow高阶操作一: 合并与分割
- 按压缩格式整理打包(解包)和压缩(解压)命令
- concat合并的数组会有顺序么_超全的JS常用数组方法整理
- Serv-U FTP Jail Break(越权遍历目录、下载任意文件)
- Android保存之SharedPreferences
- layUI日期格式转换
- 服务器运行按键精灵脚本,打开按键精灵自动运行脚本的方法_win7系统如何使用按键精灵的图文步骤...
- [c++] WINAPI
- word批量设置图片大小和对齐,使用宏定义
- C# for循环99乘法表
- 北四环的杰西·利弗莫尔:一个中国投机客的传说
- 【第七篇】Flowable核心内容之任务分配
- 孩子像谁软件在线测试,测试你最像哪个动漫人物官方版
- 免费手机号码归属地API查询接口
- 活动运营策划主要包含哪些工作内容以及如何科学完成一场活动?
- 虚拟机和本机拷贝数据: