wire
搭建下述电路:输出 等于 输入
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:单比特直通缓冲器,输入信号无逻辑改动直接传递至输出// 电路本质:纯导线连线,不产生额外逻辑门、无运算延迟,用于信号转接/层级对接moduletop_module(input in,// 1位输入端口,未显式标注类型时,Verilog默认隐式声明为wire连线型output out// 1位输出端口,assign连续赋值驱动,默认隐式wire类型);// 连续持续赋值(数据流组合逻辑写法)// 规则:输入in电平发生任意变化,输出out立刻同步跟随变化,二者电平永久一致assign out=in;endmodule输出结果
GND
搭建下述电路:
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:固定输出恒定逻辑低电平0,常用于接地信号、默认无效电平配置// 电路综合结果:输出端口直接接逻辑地,无额外组合逻辑门moduletop_module(output out// 1位输出端口,未显式指定类型,Verilog默认隐式wire连线型);// 连续赋值语句:持续驱动out为单比特常量0,电平永久固定、不受外部信号影响assign out=1'b0;endmodule输出结果
NOR
搭建下述电路:
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:实现标准2输入或非门(NOR)组合逻辑电路// 逻辑关系式:out = ~(in1 | in2),先做按位或运算、整体结果再按位取反// 真值规律:任意一路输入为高电平1,输出固定为0;仅两路同时为0,输出才为1moduletop_module(input in1,// 第1路单比特输入信号,默认隐式wire类型input in2,// 第2路单比特输入信号,默认隐式wire类型output out// 逻辑运算结果输出端口,默认隐式wire类型,适配assign连续赋值);// assign持续并行赋值:输入电平变化即时触发运算更新,纯组合逻辑无时钟延迟// 运算符拆解:| 按位或;~ 整体按位取反,括号限定先或后取反的运算顺序assign out=~(in1|in2);endmodule输出结果
Another gate
搭建下述电路:
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:实现组合逻辑运算 out = in1 & (~in2)// 逻辑含义:仅in1为高电平、in2为低电平时输出1,其余所有输入组合输出0// 电路结构:先对in2做按位取反,再和in1做按位与运算,两级纯组合逻辑门链路moduletop_module(input in1,// 第1路单比特输入,隐式wire线网类型input in2,// 第2路单比特输入,隐式wire线网类型output out// 运算结果输出,适配assign连续赋值,隐式wire类型);// assign并行持续赋值:输入电平变化即时刷新结果,无时钟、无存储延迟// 运算符说明:~ 按位取反(优先级最高);& 按位与;括号强化可读性,匹配运算顺序assign out=in1&(~in2);endmodule输出结果
Two gates
搭建下述电路:
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:三级组合逻辑运算,先对in1、in2做同或运算,结果再和in3做异或运算// 总逻辑式:out = (in1 ⊙ in2) ^ in3 (⊙代表同或,^代表异或)// 运算拆解:w1 = ~(in1 ^ in2)(同或:两输入相同输出1、不同输出0);out = w1 ^ in3moduletop_module(input in1,in2,in3,// 三路单比特输入,隐式wire连线类型output out// 最终运算结果输出,适配assign连续赋值,隐式wire类型);// 中间临时线网:保存in1、in2同或的运算结果wire w1;// 第一步:实现同或逻辑,异或取反等价同或(Verilog也可直接用~^运算符简写)assign w1=~(in1^in2);// 同或规则:in1==in2时w1=1;in1!=in2时w1=0// 第二步:同或结果w1与第三路输入in3做异或,得到最终输出assign out=w1^in3;// 异或规则:两路信号电平不同输出1、电平相同输出0endmodule输出结果
More logic gates
好的,我们来同时搭建多个逻辑门。搭建一个拥有两个输入信号a、b的组合逻辑电路,电路包含7路输出,每一路输出分别由一种逻辑门驱动:
- 与输出:a与b
- 或输出:a或b
- 异或输出:a异或b
- 与非输出:a与b的非
- 或非输出:a或b的非
- 同或输出:a同或b
- a与非b输出:a且非b
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:并行实现7种常用二输入组合逻辑运算,一次性输出所有门电路结果// 输入:a、b两路单比特信号;输出分别对应与/或/异或/与非/或非/同或/a选通非b共7路逻辑结果moduletop_module(input a,b,// 两路单比特输入,隐式wire连线类型output out_and,// 二输入与门运算结果输出output out_or,// 二输入或门运算结果输出output out_xor,// 二输入异或门运算结果输出output out_nand,// 二输入与非门运算结果输出output out_nor,// 二输入或非门运算结果输出output out_xnor,// 二输入同或门运算结果输出output out_anotb// 限定逻辑:仅a=1、b=0时输出高电平);// 1.与门:两路输入同时为1,输出才为1assign out_and=a&b;// 2.或门:任意一路输入为1,输出即为1assign out_or=a|b;// 3.异或门:两路输入电平不一致时输出1,电平一致输出0assign out_xor=a^b;// 4.与非门:先做与运算整体取反,和与门输出逻辑相反assign out_nand=~(a&b);// 5.或非门:先做或运算整体取反,和或门输出逻辑相反assign out_nor=~(a|b);// 6.同或门:异或结果取反,两路输入电平一致输出1,是异或的反向逻辑assign out_xnor=~(a^b);// 7.选通逻辑:b先取反再和a做与运算,仅满足a=1、b=0条件输出1assign out_anotb=a&(~b);endmodule输出结果
7420 chip
7400 系列是由多个逻辑门组成的数字集成电路。7420 芯片内部包含两个 4 输入与非门。 编写一个模块,实现 7420 芯片功能:共 8 路输入、2 路输出。
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:并行实现两组独立4输入与非门逻辑// 逻辑规则:4个输入全部为高电平1时输出0;只要任意1个输入为0,输出就为1moduletop_module(// 第1路4输入与非门端口定义input p1a,p1b,p1c,p1d,// 第1组与非门4路独立输入信号output p1y,// 第1组与非门运算结果输出// 第2路4输入与非门端口定义input p2a,p2b,p2c,p2d,// 第2组与非门4路独立输入信号output p2y// 第2组与非门运算结果输出);// 第一组逻辑:先对4路输入连续按位与运算,整体结果取反实现4输入与非assign p1y=~(p1a&p1b&p1c&p1d);// 第二组逻辑:独立运算,输入、输出和第一组完全隔离,互不影响assign p2y=~(p2a&p2b&p2c&p2d);endmodule输出结果
真值表
在前面的练习中,我们用到了基础逻辑门以及多组逻辑门组合而成的电路,这类电路都属于组合逻辑电路。 “组合逻辑” 的含义是:电路的输出仅仅由输入唯一决定(数学意义上的函数关系)。也就是说,给定一组确定的输入,只会对应唯一的输出结果。
因此,描述组合逻辑函数行为的一种方式,就是把每一组输入对应的输出全部罗列出来,这种表格就叫做真值表。
对于一个拥有 N 个输入的布尔函数,总共有2N2^N2N种不同的输入组合。真值表每一行代表一组输入组合,所以真值表固定有2N2^N2N行;表格的输出列则标明该组输入对应的输出电平。
上面这份真值表对应一个三输入、单输出逻辑函数。总共有 8 行,分别对应全部 8 种输入组合,附带一列输出。其中 4 组输入会让输出为 1,另外 4 组输入输出为 0。
根据真值表搭建电路
假设我们要实现上述电路,且只能使用标准逻辑门,该如何搭建任意由真值表描述的逻辑函数?
一种简单实现方法是把逻辑函数写成与或式(积之和形式,Sum-of-Products)。 “积” 代表与运算,“和” 代表或运算:
- 真值表里每一行配置一个 N 输入与门,用来检测输入是否和该行取值完全匹配;
- 再用一个或门,把所有输出结果为 1 的行对应的与门输出做或运算。
以本例说明: 当输入匹配第 2 行、第 3 行、第 5 行或第 7 行时,输出为 1,因此后端用一个4 输入或门汇总这四路信号。 以第 2 行为例:输入满足 x3=0、x2=1、x1=0,这一路用一个3 输入与门识别该输入组合。 综上,该真值表的标准规范实现方式为:4 个三输入与门输出接到同一个四输入或门。
练习
设计一个组合逻辑电路,实现上面这张真值表对应的逻辑功能。
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:实现三变量组合逻辑 f = (~x3 & x2) | (x3 & x1)(典型多路选择型与或逻辑)// 逻辑含义:x3=0时输出跟随x2;x3=1时输出跟随x1,等价二选一多路选择器功能moduletop_module(input x3,// 高位控制/输入变量input x2,// 分支输入变量1(x3低电平有效通路)input x1,// 分支输入变量2(x3高电平有效通路)output f// 最终逻辑运算结果输出);// 运算拆解:// 项1:~x3 & x2 (x3取反后和x2相与,x3=0、x2=1时该项成立)// 项2:x3 & x1 (x3直接和x1相与,x3=1、x1=1时该项成立)// 两项做或运算,任意一项满足条件输出即为1assign f=((~x3)&x2)|(x3&x1);endmodule输出结果
两位相等比较器
取自 2015 年期中试卷第 1k 题 搭建电路:两路 2 位向量输入 A[1:0]、B[1:0],输出单比特 z。 当 A 与 B 数值完全相等时 z=1,否则 z=0。
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:2位向量相等比较器,两路输入数值完全一致输出高电平1,不一致输出低电平0moduletop_module(input[1:0]A,// 2位输入向量,A[1]高位、A[0]低位input[1:0]B,// 2位输入向量,B[1]高位、B[0]低位output z// 比较结果输出:A==B则z=1,反之z=0);// 三元运算符格式:条件表达式 ? 条件成立取值 : 条件不成立取值// == 按位全等比较运算符,逐位对比A、B所有比特是否全部相同assign z=(A==B)?1:0;endmodule输出结果
简单电路A
出自 2015 年期中试卷第 4 题 模块功能实现逻辑:z=(x⊕y)⋅xz = (x \oplus y) \cdot xz=(x⊕y)⋅x
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:实现组合逻辑 z = (x ^ y) & x// 运算顺序:先对x、y做异或运算,结果再和x执行按位与运算moduletop_module(input x,// 单比特输入信号x,默认隐式wire类型input y,// 单比特输入信号y,默认隐式wire类型output z// 逻辑运算结果输出,适配assign连续赋值);// 运算符说明:^ 异或(两信号不同输出1、相同输出0);& 按位与// 括号固定运算优先级:优先完成异或,再执行与运算assign z=(x^y)&x;endmodule输出结果
简单电路B
出自 2015 年期中试卷第 4 题 电路 B 的功能由下方仿真波形描述
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:实现二输入同或门组合逻辑运算// 逻辑规则:两路输入电平完全相同输出1,电平不同输出0// 数学表达式:z = ~(x ^ y),异或结果整体取反等价同或运算moduletop_module(input x,// 单比特输入信号x,默认隐式wire连线类型input y,// 单比特输入信号y,默认隐式wire连线类型output z// 同或运算结果输出,适配assign连续并行赋值);// 运算拆解:^ 异或(x、y不一致输出1);~ 整体按位取反得到同或结果// 括号不可省略:必须先完成异或运算,再对最终结果取反assign z=~(x^y);endmodule输出结果
组合电路A和电路B
本题选自 2015 年期中试卷第 4 题。 本设计会用到子模块 mt2015_q4a(子电路 A)与 mt2015_q4b(子电路 B),请先查看这两个子模块的定义。 顶层电路结构如下图所示:分别例化2 个子电路 A、2 个子电路 B。
A模块逻辑: z = (x^y) & x
B模块逻辑:z = ~(x^y)
参考答案
// synthesis verilog_input_version verilog_2001//=============================================// 子模块 m_a:基础组合逻辑单元// 逻辑公式:z = (x ^ y) & x// 逻辑简化等价:z = x & ~y,仅x=1、y=0时输出高电平//=============================================modulem_a(input x,// 单比特输入xinput y,// 单比特输入youtput z// 运算结果输出);// 先异或、再按位与,括号明确运算先后顺序assign z=(x^y)&x;endmodule//=============================================// 子模块 m_b:二输入同或门单元// 逻辑公式:z = ~(x ^ y)// 逻辑规则:x、y电平完全相同输出1,电平不同输出0//=============================================modulem_b(input x,// 单比特输入xinput y,// 单比特输入youtput z// 同或结果输出);// 异或整体取反实现同或,括号不可省略,避免仅x单独取反assign z=~(x^y);endmodule//=============================================// 顶层模块 top_module:多层级模块化组合逻辑电路// 整体运算链路:// 1.两路m_a、两路m_b并行接收全局x/y,得到4组中间结果// 2.z_n[0]、z_n[1]做或运算;z_n[2]、z_n[3]做与运算// 3.两组中间结果异或,得到最终输出z//=============================================moduletop_module(input x,// 全局公共输入信号x,供给所有子模块input y,// 全局公共输入信号y,供给所有子模块output z// 电路最终运算结果输出);// 6位内部中间总线:缓存各级模块运算结果,位宽0~5依次存储分步结果wire[5:0]z_n;// 实例化第1个A子模块:输入全局x/y,结果存入z_n最低位z_n[0]m_aia1(.x(x),.y(y),.z(z_n[0]));// 实例化第1个B子模块:输入全局x/y,结果存入z_n[1]m_bib1(.x(x),.y(y),.z(z_n[1]));// 实例化第2个A子模块:复用全局输入,独立运算,结果存入z_n[2]m_aia2(.x(x),.y(y),.z(z_n[2]));// 实例化第2个B子模块:复用全局输入,独立运算,结果存入z_n[3]m_bib2(.x(x),.y(y),.z(z_n[3]));// 第一级组合运算:前两组子模块结果做按位或assign z_n[4]=z_n[0]|z_n[1];// 第一级组合运算:后两组子模块结果做按位与assign z_n[5]=z_n[2]&z_n[3];// 最终运算:两组一级运算结果做异或,输出全局最终信号assign z=z_n[4]^z_n[5];endmodule输出结果
响铃或震动
假设你要设计一个电路,用于控制手机的铃声和震动马达。 当有来电需要响铃时(输入信号 ring=1),电路必须只开启铃声(输出 ringer=1)或只开启马达(输出 motor=1),二者不能同时打开。 如果手机处于震动模式(输入 vibrate_mode=1),则开启马达;否则开启铃声。
请仅使用 assign 连续赋值语句完成设计,练习将文字需求转化为逻辑门电路。
设计思路提示
设计硬件电路时,常常需要逆向推导:从输出的约束条件出发,反向推导输入逻辑;这和顺序式编程思维完全相反。
- 软件(顺序、指令式)思维习惯:先看输入,再判断输出行为 句式:如果(输入满足XX),则执行XX输出
- 硬件(组合逻辑)思维习惯:先明确输出何时为 1,再写等式 句式:输出=1 的充要条件是(输入满足XX)
本题需求是软件式的指令描述(如果来电就执行对应动作),你需要把它转换成硬件可用的声明式赋值 assign ringer = 逻辑表达式;。 熟练切换、翻译这两种思维模式,是硬件设计最重要的核心能力之一。
参考答案
// synthesis verilog_input_version verilog_2001// 模块功能:手机来电提示模式控制逻辑,根据震动模式开关切换响铃/震动两种提示方式// 逻辑规则:来电信号ring为高电平时生效;vibrate_mode=0开启铃声、vibrate_mode=1开启震动,二者互斥moduletop_module(input ring,// 来电触发输入:高电平=有来电,低电平=无来电input vibrate_mode,// 模式选择输入:1=震动模式,0=响铃模式output ringer,// 铃声驱动输出:1=播放铃声,0=关闭铃声output motor// 马达驱动输出:1=启动震动,0=关闭震动);// 铃声开启条件:存在来电 + 未开启震动模式,两个条件同时满足才响铃assign ringer=ring&~vibrate_mode;// 震动开启条件:存在来电 + 开启震动模式,两个条件同时满足才启动马达assign motor=ring&vibrate_mode;endmodule输出结果
恒温器
一款冷暖恒温器可分别控制冬季加热器与夏季空调。请设计电路,合理控制加热器、空调与送风风扇的启停。
恒温器分为两种工作模式:制热模式(mode = 1)、制冷模式(mode = 0)。
- 制热模式下:当环境温度过低(too_cold = 1)时开启加热器,空调保持关闭;
- 制冷模式下:当环境温度过高(too_hot = 1)时开启空调,加热器保持关闭;
- 只要加热器或空调任意一台设备开启,风扇必须同步启动以循环空气;
- 额外功能:即便加热器、空调全部关闭,用户也可手动强制开启风扇(fan_on = 1)。
要求:仅使用assign连续赋值语句完成设计,练习将文字需求转化为逻辑门电路。
参考答案
// synthesis verilog_input_version verilog_2001//-----------------------------------------------------------------------------// 模块名称:top_module// 功能概述:空调系统温控联动控制模块,依据温度检测、工作模式启停加热/制冷设备,// 风扇支持设备联动开启+用户手动强制开启两种触发方式// 设计特性:加热、制冷互斥运行;风扇多条件并行触发,纯组合逻辑实时响应//-----------------------------------------------------------------------------moduletop_module(input too_cold,// 温度检测输入:1-环境温度过低,需制热;0-温度正常input too_hot,// 温度检测输入:1-环境温度过高,需制冷;0-温度正常input mode,// 运行模式选择:1-制热模式;0-制冷模式input fan_on,// 风扇手动控制:1-用户强制开风扇;0-跟随温控自动控制output heater,// 加热器控制输出:1-启动加热;0-关闭加热output aircon,// 制冷空调控制输出:1-启动制冷;0-关闭制冷output fan// 循环风扇控制输出:1-风扇运转;0-风扇停机);// 制热逻辑约束:仅制热模式+低温触发,开启加热器assign heater=mode&too_cold;// 制冷逻辑约束:仅制冷模式+高温触发,开启空调(mode取反筛选制冷档位)assign aircon=~mode&too_hot;// 风扇触发规则:加热运行 / 制冷运行 / 手动强制开启,任一条件满足即运转assign fan=heater|aircon|fan_on;endmodule输出结果
位统计电路
位统计电路(popcount)” 用于统计输入向量中逻辑 1 的总位数,请设计一个 3 位输入的位统计电路
参考答案
// synthesis verilog_input_version verilog_2001//-----------------------------------------------------------------------------// 模块名称:top_module// 功能概述:3bit输入向量内高电平1计数模块,统计输入3位中逻辑1的总数量,用2bit输出结果// 设计特性:纯组合逻辑逐位累加计数,最大计数值3,2位输出可完整覆盖0~3范围//-----------------------------------------------------------------------------moduletop_module(input[2:0]in,// 3位输入向量:in[2]高位、in[0]低位,待统计1的个数output[1:0]out// 2位计数输出:取值范围0~3,对应输入里逻辑1的总数量);// 计数逻辑:单比特信号参与算术运算,电平1数值为1、电平0数值为0,逐位相加得到总数assign out=in[0]+in[1]+in[2];endmodule输出结果
逻辑门与位向量
给定一个 4 位输入向量 in[3:0],要求求出每一位与其相邻比特之间的逻辑关系,分三组输出:
- out_both:输出向量的每一位用于标记:本位输入比特 和 它左边相邻比特(下标更大的那位)是否同时为 1。 例:out_both[2] 判断 in[2] 和它左侧邻居 in[3] 是否全为 1。in[3] 左侧没有比特,因此 out_both[3] 无实际作用,无需计算有效逻辑。
- out_any:输出向量每一位标记:本位输入比特 和 它右侧相邻比特 是否至少有一个为 1。 例:out_any[2] 判断 in[2]、右邻 in[1] 是否至少一个是 1。in[0] 右侧无比特,out_any[0] 无意义。
- out_different:输出每一位标记:本位比特 和 左侧邻居比特取值是否不相等。 例:out_different[2] 判断 in[2] 与左邻 in[3] 是否相异。 本组为环形首尾相接:in[3] 的左邻是最低位 in[0]。
参考答案
// synthesis verilog_input_version verilog_2001//-----------------------------------------------------------------------------// 模块名称:top_module// 功能概述:4bit向量邻位并行判断模块,分三类逻辑输出:// 1.out_both:逐位对比本位+左侧相邻位,两位同时为1则标记1(最高位无左邻舍弃)// 2.out_any:逐位对比本位+右侧相邻位,任意一位为1则标记1(最低位无右邻舍弃)// 3.out_different:环形首尾衔接对比本位+左邻,电平不一致则标记1(完整4位输出)// 设计特性:纯组合逻辑错位位运算,并行高效完成邻位判断//-----------------------------------------------------------------------------moduletop_module(input[3:0]in,// 4位输入向量,位序高位in[3]~低位in[0]output[2:0]out_both,// 3bit输出:in[2:0]分别和左邻in[3:1]按位与结果output[3:1]out_any,// 3bit输出:in[3:1]分别和右邻in[2:0]按位或结果output[3:0]out_different// 4bit环形异或输出,本位与环形左邻不同则置1);// 逻辑:本位 & 左侧相邻位,仅两位全1输出1;高位对齐截取低3位,舍弃无左邻的in[3]assign out_both=in&in[3:1];// 逻辑:本位 | 右侧相邻位,任意一位为1输出1;低位对齐截取高3位,舍弃无右邻的in[0]assign out_any=in[3:1]|in;// 逻辑环形错位拼接:{in[0],in[3:1]} 实现首尾衔接左移一位,异或判断相邻电平是否不一致assign out_different=in^{in[0],in[3:1]};endmodule输出结果
更长位宽向量
给定一个 100 位输入向量 in[99:0],需要求出每一位与其相邻比特的三种逻辑关系输出:
- out_both 输出向量每一位标记:本位输入比特 和 它左侧相邻比特(下标更大的高位)是否同时为 1。 举例:out_both[98] 判断 in[98] 和左侧邻居 in[99] 是否全 1。in[99] 左侧没有比特,因此无需定义 / 计算 out_both[99]。
- out_any 输出向量每一位标记:本位输入比特 和 它右侧相邻比特(下标更小的低位)是否至少有一个为 1。 举例:out_any[2] 判断 in[2]、右邻 in[1] 是否至少有一个为 1。in[0] 右侧无比特,无需定义 / 计算 out_any[0]。
- out_different 输出向量每一位标记:本位比特 和 左侧邻居比特取值是否不相等。 举例:out_different[98] 判断 in[98] 与左邻 in[99] 是否相异。 本组向量为环形首尾相连:in[99] 的左邻居是最低位 in[0]。
参考答案
// synthesis verilog_input_version verilog_2001//-----------------------------------------------------------------------------// 模块名称:top_module// 对应习题:Even longer vectors(更长位宽向量邻位检测)// 功能概述:100bit超宽输入向量做三类邻位并行逻辑判断// 1. out_both:本位与左侧相邻位同时为1则输出1,舍弃最高位in[99](无左邻),输出位宽99bit// 2. out_any:本位与右侧相邻位任意一个为1则输出1,舍弃最低位in[0](无右邻),输出位宽99bit// 3. out_different:首尾环形衔接,本位与环形左邻电平不一致输出1,完整保留100bit输出// 设计特性:纯组合错位位运算,逻辑可直接平移复用至任意位宽向量//-----------------------------------------------------------------------------moduletop_module(input[99:0]in,// 100位输入总线,高位in[99] ~ 低位in[0]output[98:0]out_both,// 邻位全1标记:out_both[i]=in[i]&in[i+1], i∈[0,98]output[99:1]out_any,// 邻位至少1个1标记:out_any[i]=in[i]|in[i-1], i∈[1,99]output[99:0]out_different// 环形邻位差异标记:本位和循环左移一位相邻位不同置1);// 错位按位与:in[98:0]逐位和左邻in[99:1]相与,高位自动截断匹配99bit输出assign out_both=in&in[99:1];// 错位按位或:in[99:1]逐位和右邻in[98:0]相或,低位自动截断匹配[99:1]输出范围assign out_any=in[99:1]|in;// 位拼接构造循环左移1位向量:最低位in[0]补到最高位,剩余高位整体右移一位// 异或运算检测相邻电平差异,两值不等输出1,实现首尾闭环环形对比assign out_different=in^{in[0],in[99:1]};endmodule