【Verilog学习】-06-组合电路
这一章主要对组合逻辑电路的设计做了一个复习,前面也有比较多的涉及,因此下面仅记录一些关键点。
硬件设计思路
这里与软件的涉及不同,硬件设计主要是逆向的思考,即由想要的输出决定输入(assign ringer = ··· )。
Design hint: When designing circuits, one often has to think of the problem “backwards”, starting from the outputs then working backwards towards the inputs. This is often the opposite of how one would think about a (sequential, imperative) programming problem, where one would look at the inputs first then decide on an action (or output). For sequential programs, one would often think “If (inputs are ___ ) then (output should be ___ )”. On the other hand, hardware designers often think “The (output should be ___ ) when (inputs are ___ )”.
The above problem description is written in an imperative form suitable for software programming (if ring then do this), so you must convert it to a more declarative form suitable for hardware implementation (
*assign ringer = ___*
). Being able to think in, and translate between, both styles is one of the most important skills needed for hardware design.
这道题比较有意思:
You are given a 100-bit input vector in[99:0]. We want to know some relationships between each bit and its neighbour:
- out_both: Each bit of this output vector should indicate whether both the corresponding input bit and its neighbour to the left are ‘1’. For example,
out_both[98]
should indicate ifin[98]
andin[99]
are both 1. Sincein[99]
has no neighbour to the left, the answer is obvious so we don’t need to knowout_both[99]
.- out_any: Each bit of this output vector should indicate whether any of the corresponding input bit and its neighbour to the right are ‘1’. For example,
out_any[2]
should indicate if eitherin[2]
orin[1]
are 1. Sincein[0]
has no neighbour to the right, the answer is obvious so we don’t need to knowout_any[0]
.- out_different: Each bit of this output vector should indicate whether the corresponding input bit is different from its neighbour to the left. For example,
out_different[98]
should indicate ifin[98]
is different fromin[99]
. For this part, treat the vector as wrapping around, soin[99]
‘s neighbour to the left isin[0]
.
solution:
1 | module top_module ( |
可以用向量操作,比循环更方便。
多路选择器
assign方式
assign out = sel ? b : a;
assign out[99:0] = sel ? b[99:0] , a[99:0];
1 | module top_module( |
case 方式(适用于较多的情况)
1 | always @(*) begin |
在写Verilog的时候比较好的习惯是写一个begin就写一个end,避免出现语法错误。
加法器
全加器的写法在05节中已经详细讨论过,这里也可以使用verilog自带的+法。
1 | module top_module ( |
补码加法及其溢出判断
通过比较输入输出的符号(–得+,++得-为溢出):
1 | module top_module ( |
通过比较最高两位的溢出:(因此要计算出所有的进位)
1 | module top_module ( |
100位的全加器(使用+)
1 | module top_module( |
05章节里里面的方法更为原始直接。
BCD adder
1 | module top_module( |
再谈多路选择器
Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel=0 should select bits
in[3:0]
, sel=1 selects bitsin[7:4]
, sel=2 selects bitsin[11:8]
, etc.
这道题涉及到的问题是由于不能够直接使用in[ sel * 4+3 : sel* 4 ]
,因为变量sel的宽度不确定。
博客中,给了更为紧凑的语法,就是Indexed vector part select(下标向量的部分选择)[^1]。
代码如下:
1 | module top_module( |
题目分析如下,当输入有一个发生变化时(相邻的方格中可以看到),输出就会发生反转。就是输入异或的结果。
也可以通过化简SOP得到。
[^1]: Verilog-2001的向量部分选择_LuchangLi 的专栏-CSDN博客_verilog 向量部分选择