HDLBits(4) Procedures合集
Procedures
- Alwaysblock1:combinational
- Problem Statement
- Writing Code
- Alwaysblock2:clocked
- 阻塞 VS 非阻塞赋值
- Problem Statement
- Writing Code
- Always if:if statement
- Problem Statement
- Writing Code
- Always if2:if statement latches
- Problem Statement
- Writing Code
- Always case:case statement
- Problem Statement
- Writing Code
- Always case2:priority encoder
- Problem Statement
- Hint
- Writing Code
- Always casez:priority encoder with casez
- Problem Statement
- Hint
- Writing Code
Alwaysblock1:combinational
由于数字电路是由连接电线的逻辑门组成的,任何电路都可以表示为一些模块和赋值语句的组合。然而,有时这并不是描述电路最方便的方法。过程(block总是一个例子)提供了描述电路的另一种语法。
有两种类型的always块是与可综合硬件相关的:
组合逻辑: always @(*)
时序逻辑: always @(posedge clk)
always块等价于赋值语句,因此总是有两种方式来表达一个组合电路。选择使用哪个方法主要是哪个语法更方便的问题。过程块内部代码的语法与外部代码不同。过程块有更丰富的语句集(例如if-then, case),不能包含连续的赋值,但也引入了许多新的不直观的出错方法。
例如,赋值语句和组合always块描述相同的电路。两者都创建了相同的组合逻辑。当任何输入(右侧)更改值时,两者都将重新计算输出。
assign out1 = a & b | c ^ d;
always @(*) out2 = a & b | c ^ d;
对于组合always块,总是使用(*)的敏感性列表。明确列出信号是很容易出错的(如果您错过了一个),并且在硬件合成时被忽略。如果你显式地指定了灵敏度列表并且错过了一个信号,合成的硬件仍然会表现得像指定了 ( * ) 一样,但是模拟将不匹配硬件的行为。(在SystemVerilog中,使用always_comb。)
关于wire和reg的注意事项:赋值语句的左边必须是net类型(例如wire),而过程赋值语句(在always块中)的左边必须是变量类型(例如reg)。这些类型(wire vs. reg)与合成什么硬件无关,只是Verilog作为硬件模拟语言使用时遗留下来的语法。
Problem Statement
使用assign语句和组合的always块构建与门。(因为赋值语句和组合语句总是相同地阻塞函数,所以没有办法强制你同时使用这两种方法。但你是来练习的,对吧?)
Writing Code
// synthesis verilog_input_version verilog_2001
module top_module(input a, input b,output wire out_assign,//赋值语句左侧用wireoutput reg out_alwaysblock//always中的过程赋值语句用reg//用两种方式,两种输出
);//assign statementassign out_assign = a & b;//combinational always blockalways@(*) beginout_alwaysblock = a & b;endendmodule
Alwaysblock2:clocked
对于硬件合成,有两种类型的总是相关的块:
组合:always @(*)
时序:always @(posedge clk)
时序always块创建一组组合逻辑像组合always块一样,但也在组合逻辑输出处创建一组触发器(或“寄存器”)。不像逻辑的输出是立即可见的,它的输出而是在下一个(posedge clk)之后才可见。
阻塞 VS 非阻塞赋值
在Verilog中存在三种赋值:
·连续赋值(assign x = y;):不能在过程(“always块”)中使用。
·过程阻塞赋值(x = y;):只能在过程中使用。
·过程非阻塞赋值(x <= y;):只能在过程中使用。
划重点!
在组合always块中,使用阻塞性赋值。在时序always块中,使用非阻塞性赋值。完全理解是为什么对硬件设计用处不大,还需要理解Verilog模拟器如何跟踪事件不遵循这一规则就很难发现仿真和综合硬件之间既不确定又不同的错误。
Problem Statement
使用赋值语句、组合always块和时钟always块三种方法构建异或门。注意,时钟always块产生一个不同于其他两个的电路:有一个触发器,所以输出被延迟。
Writing Code
// synthesis verilog_input_version verilog_2001
module top_module(input clk,input a,input b,output wire out_assign,//赋值语句用wireoutput reg out_always_comb,//过程块always @(*)用regoutput reg out_always_ff );//过程块always @(posedge clk)用regassign out_assign = a^b;always @(*)beginout_always_comb = a^b;endalways @(posedge clk)beginout_always_ff <= a^b;//注意这儿是<=阻塞式赋值!endendmodule
解释:为啥下面这个地方不一样但是还是success了
前文有一句:
“注意,时钟always块产生一个不同于其他两个的电路:有一个触发器,所以输出被延迟。”
“时序always块创建一组组合逻辑像组合always块一样,但也在组合逻辑输出处创建一组触发器(或“寄存器”)。不像逻辑的输出是立即可见的,它的输出而是在下一个(posedge clk)之后才可见。”
另外一方面的解释是:always @(posedge clk)begin
与正规的相比,少了一个下降沿复位的信号,也就是一开始的状态。此时没有,所以说并不是一开始就是复位状态的,是不定态的。
Always if:if statement
if语句通常创建一个2选1的多路复用器,如果条件为真,则选择一个输入;如果条件为假,则选择另一个输入。
always @(*) beginif (condition) beginout = x;endelse beginout = y;end
end
//注意格式!有begin就有end,有if 就要有else,case必跟default
这相当于使用带有条件运算符的连续赋值语句:
assign out = (condition) ? x : y;
然而,if语句提供了一种新的出错方法。只有当输出被赋值时,电路才是组合的。
Problem Statement
构建一个在a和b之间进行选择的2选1数据选择器。如果sel_b1和sel_b2 都为真,选择b;否则选择a。实现两次,一次用赋值语句,一次用if语句。
Writing Code
// 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 ); //如果sel_b1和sel_b2 都为真,选择b;否则选择aassign out_assign = (sel_b1 && sel_b2)?b:a;always @(*) beginif(sel_b1 && sel_b2)out_always = b;else out_always = a;endendmodule
Always if2:if statement latches
Problem Statement
常见的错误来源:如何避免产生锁存器?
在设计电路时,关于电路必须首先考虑:
·我想要这个逻辑门
·我想要一个逻辑组合块,它有一些输入,产生这一些输出
·我想要一个逻辑组合块,后面带有触发器
你千万不能先写代码,然后希望它能产生一个合适的电路。
If (cpu_overheated) then shut_off_computer = 1;
If (~arrived) then keep_driving = ~gas_tank_empty;
语法正确的代码不一定会产生合理的电路(组合逻辑+触发器)。通常的原因是:“除了您指定的那些情况之外,在其他情况下会发生什么?”Verilog的答案是:保持输出不变(产生锁存)。
“除了您指定的那些情况之外,在其他情况下会发生什么?”这应该是我们该突破的思维误区
这种“保持输出不变的行为”意味着需要记住当前状态,从而产生一个锁存器。组合逻辑(例如,逻辑门)不能记住任何状态。注意“Warning (10240): … inferring latch(es)”信息。除非锁存是故意的,否则它几乎总是指出一个bug。组合电路必须在所有条件下都有一个值分配给输出。这通常意味着你总是需要else子句或默认赋值给输出。
以下代码包含产生锁存器的不正确行为。
修复漏洞,这样只有在电脑过热的时候你才会关掉电脑,当你到达目的地或者需要加油的时候才会停止开车(原作者的形象解释)。
always @(*) beginif (cpu_overheated)shut_off_computer = 1;
endalways @(*) beginif (~arrived)keep_driving = ~gas_tank_empty;
end
Writing Code
// 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;//只有在电脑过热的时候你才会关掉电脑else shut_off_computer = 0;//其它时刻电脑都在运行endalways @(*) beginif (~arrived)//没到达时keep_driving = ~gas_tank_empty;//当你 到达目的地 或者 需要加油的时候 才会停止开车//此处意为:有油的时候就继续keep_drivingelse //到达的时候keep_driving = ~arrived;endendmodule
总结:if必须带else
case必须带default和endcase
Always case:case statement
Verilog中的Case语句几乎等同于if-elseif-else序列,它将一个表达式与其他表达式列表进行比较。它的语法和功能不同于C语言中的switch语句。
always @(*) begin //这是一个组合电路case (in)1'b1: begin out = 1'b1; //如果超过了1个语句,就要用begin-end了,相当于{ }end1'b0: out = 1'b0;default: out = 1'bx;endcase
end
·case语句以case开头,每个“case item”以冒号结束。switch语句没有。
·每个case项可以只执行一条语句。这使得C语言中使用的**“break”在这里没有必要**。如果需要多个语句,则必须使用begin…end。
·重复的(和部分重复)的case是允许的。使用第一个匹配的。C不允许重复案例项目。
Problem Statement
如果在有许多种的情况下,case语句比if语句更方便。因此,在这个练习中,创建一个6对1的多路复用器。当sel在0到5之间时,选择相应的数据输入。否则,输出0。数据输入和输出都是4位宽。
Writing Code
// 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'd0是不行的,注意数据格式3'b001 : out = data1;3'b010 : out = data2;3'b011 : out = data3;3'b100 : out = data4;3'b101 : out = data5;default:out = 4'b0;endcase endendmodule
Always case2:priority encoder
优先级编码器是一种组合电路,当给定一个输入位向量时,输出向量中第一个1位的位置。例如,给定输入8’b10010000的8位优先级编码器将输出3’d4,因为位[4]是第一个高的位。
注意:是从低位到高位!
Problem Statement
构建一个4位优先级编码器。如果没有一个输入位是高的(例如输入为零),那么输出为零。注意,一个4位数字有16种可能的组合。
Hint
使用十六进制(4’hb)或十进制(4’d11)数字字面值会比二进制(4’b1011)字面值节省键入时间。
Writing Code
因为是第一位的位置,所以说4位的优先级编码器,也就0、1、2、3四种输出结果。
那如何匹配in呢?
抓住几个关键的数字
比如0001、0011、0111、是1
是3
0100是4
1000是8
那么之间的都是输出的某一个固定的数字
加粗样式
为了便于理解和区分:我在下面的程序进行了“分段”
以下是官方的答案,但是我更喜欢我的答案
module top_module (input [3:0] in,output reg [1:0] pos
);always @(*) begin // Combinational always blockcase (in)//16种情况4'h0: pos = 2'h0; // I like hexadecimal 16进制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.endcaseend// There is an easier way to code this. See the next problem (always_casez).endmodule
我更喜欢我的答案,因为虽然最后的输出是2进制的,但是我更喜欢前面in的情况用二进制来看,相对于16进制来说,不容易出错
// 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
Always casez:priority encoder with casez
Problem Statement
构建一个8位输入优先级编码器。给定一个8位向量,输出应该指出向量中的第一个是1的位。如果输入向量没有1,则输出0。例如,输入8’b10010000应该输出3’d4,因为位[4]是第一个高(为“1”)的位。
与上一次不同的地方在于,这一次是8位,情况更多了,该如何处理??
根据前面的练习(Always_case2), case语句中有256种情况。如果case语句中的case项支持“不关心”位,我们可以将其减少(减少到9种情况)。
这就是casez的作用:它将值z的位视为比较中不关心的位。
例如,这将实现之前练习中的4输入优先级编码器:
always @(*) begincasez (in[3:0])4'bzzz1: out = 0; // in[3:1] can be anything4'bzz1z: out = 1;4'bz1zz: out = 2;4'b1zzz: out = 3;default: out = 0;endcase
end
case语句的行为就像按顺序检查每一项一样(实际上,它做的事情更像是生成一个巨大的真值表,而不是生成门)。注意某些输入(例如,4’b1111)如何匹配多个case项。选择第一个匹配项(因此4’b1111匹配第一个项out = 0,但不匹配后面的任何项)。
还有一个类似的casex,它把x和z都当作“不关心”。我看不出它比casez有更多的用处。
符号?是z的同义词,所以2’bz0和2’b?0相同。
Hint
这里必须使用二进制文字,因为需要为某些位指定z。
Writing Code
HDLBits(4) Procedures合集相关推荐
- HDLBits刷题合集—9 Arithmetic Circuits
HDLBits刷题合集-9 Arithmetic Circuits HDLBits-66 Hadd Problem Statement 创建一个半加器.半加器将两个输入(不带低位的进位)相加产生和和向 ...
- 入门指南目录页 -PaddlePaddle 飞桨 入门指南 FAQ合集-深度学习问题
入门指南目录页 -PaddlePaddle 飞桨 入门指南 FAQ合集 GT_Zhang关注 0.1012019.08.01 18:43:34字数 1,874阅读 795 Hi,欢迎各位来自Paddl ...
- 全文翻译(全文合集):TVM: An Automated End-to-End Optimizing Compiler for Deep Learning
全文翻译(全文合集):TVM: An Automated End-to-End Optimizing Compiler for Deep Learning 摘要 人们越来越需要将机器学习应用到各种各样 ...
- Open3D点云处理算法最全合集
Open3D点云处理算法最全合集,致力于搜集可运行,可视化较好的Open3D算法,持续更新中- 1. Open3D 点云读取及可视化.离群点去除 2. Open3D 点云体素格下采样 3. Open3 ...
- JAVA Web项目中所出现错误及解决方式合集(不断更新中)
JAVA Web项目中所出现错误及解决方式合集 前言 一.几个或许会用到的软件下载官网 二.Eclipse的[preferences]下没有[sever]选项 三.Tomcat的安装路径找不到 四.T ...
- 一、PyTorch Cookbook(常用代码合集)
PyTorch Cookbook(常用代码合集) 原文链接:https://mp.weixin.qq.com/s/7at6y2NcYaxGGN8syxlccA 谢谢作者的付出.
- cookie和url参数获取的常规实用方法合集(ES6)
//获取某一个cookie的值 const getCookie = key => {var k = key, dc = document.cookie;if (dc.length > 0) ...
- 《团队合作大坑合集》
1.百分号无限循环小数 2.小数四舍五入计算错误 3.写死了年份导致跨年无法选择最新年份 4.悄悄修改内外网访问限制导致外网接口不能访问 5.定位索引城市的地理坐标,定位到了同名的其他城市 6.更新包 ...
- 【对接】《前后端对接联调数据、调试接口过程乌龙大合集》
<团队合作大坑合集>_←你挚爱的强哥→的博客-CSDN博客1.百分号无限循环小数2.小数四舍五入计算错误3.写死了年份导致跨年无法选择最新年份4.悄悄修改内外网访问限制导致外网接口不能访问 ...
最新文章
- Matlab中imagesc用法
- How to remove the dotted border on Active link state---移除链接激活时出现的虚线
- byteman_Byteman –用于字节码操纵的瑞士军刀
- form表单图片预览 layui_layui 实现图片上传和预览
- python--文件
- easypoi 导入oracle,记一次由openjdk导致的poi错误(easyexcel)
- go语言学习路线图_开篇:Go 语言的优势与学习路线图
- 小米手机一键刷入bl锁重锁_OPPO手机完美安装Kingroot实现一键root
- opencv人脸检测报错,(-215:Assertion failed)cv::CascadeClassifier::detectMultiScale‘
- oracle 建表sql语句,oracle 建表sql语句
- php面包屑导航实现思路,简单实现面包屑导航代码
- android hook 第三方app_Android Hook技术
- 如何通俗的解释全微分?
- JSAAS的Activiti会签开发扩展处理
- SQLyog:Error Code : 1583 Incorrect parameters in the call to native function ‘concat‘
- Mac电脑快速切换用户教程
- AD ADSI入门
- 核心交换机、汇聚交换机、接入交换机
- 2023牛客寒假算法基础集训营1
- 通过修改注册表激活 Windows 操作系统
热门文章
- hp mfp m281fdw 彩色激光打印机不通电
- remind me of 2009
- 谭咏麟-讲不出再见-国语谐音歌词
- 消费互联网、产业互联网、工业互联网、能源互联网的关键区别是什么?智慧城市、智慧园区、智慧交通、智慧水务、智能电网、智慧工厂中都需要的关键技术是什么?
- 【Apache Mina2.0开发之一】搭建Apache Mina框架并实现Server与Client端消息传递
- 快充伤电池?我来帮何同学做个假设检验
- 2022焊工(高级)培训试题及答案
- 计算机历史和未来课程,计算机课程作业,计算机与汽车结合的历史与未来ppt概要.ppt...
- python签到教程_Python实现自动签到
- 百科:天然药物化学家--曾广方