回顾去年底写的计划,发现还有好多没做。在接下来的一个月里面得抓紧时间得把没有完成的工作完成了。
而这个里面其中有一个重头戏就是得把新版的《数字电路与系统设计》这本书初稿给搞完了。这是一本新的书。要彻底改变过去那种数字电路只讲74,和EDA/硬件描述语言“两张皮”的现象,就意味着要彻底改变现有教材的体系结构,所以还真是不太好写。
但不好写也总归是要写的。我的计划是先在一些关键节点上取得突破,然后根据旧的资料重新组合到一起。由点及面,小的突破带动大的改变。
为了尽早的把改革成果带给大家,也为了检验编写方法是否合适。我决定先在知乎上发表零星的一些关键节点的改变,接受大家的审阅。
今天要谈的问题是:硬件描述语言的三种形式及其与数字电路与系统的对应关系。
首先我们要明确一点,硬件描述语言是“描述硬件的语言”,是在“描述”硬件。换言之,就是在阐述某个事物“长得什么”。对于现代大规模数字电路与系统设计,很大程度上依赖计算机辅助的自动化设计流程。而自动化设计的起点是需要设计人员通过某种方式“告知”计算机需要设计的电路是个什么样子,然后通过运行自动化设计软件将整个数字系统自动的“产生”出来。
对于一个已知数字电路,应该怎么来描述这个数字电路呢?我们通过一个实例来看。
图1 本文采用的范例
对于这样一个逻辑电路,首先我们应该明确这个电路的输入和输出。所以在硬件描述语言的时候首先要声明输入输出端口。我们以Verilog HDL为例来看,应该这么写:
module example (a, b, c, y);
input a,b,c;
output y;
……
……
endmodule
如果我们把这段代码翻译成“人话”就应该这么来说:我们把这个电路模块命名为example,它有四个端口。其中有三个输入端口,分别叫a、b、c;有一个输出端口,名字叫y。再对比图1,我们会发现这就是把“人话”用代码说出来了而已。
好了,下一步我们需要描述这个电路的具体功能了。我们下面采取先说“人话”,再写代码的方式。
第一种说话的方式,就是最直观的“按图说话”。对着这张图,我们可以通过描述电子元件(逻辑门)之间的连接关系来描述。为了更方便的说话,我们可以把图改成这样:
图2 添加了中间信号和元器件名的电路图
图2中,我们在电路图里面增加了e和f两个中间变量,并对是有的元器件(逻辑门)都命名了。所以我们可以按以下的方法来说“人话”:
有一个元件叫U1,是一个两输入与门;它的输入是a和b,输出是e;
有一个元件叫U2,是一个非门(反相器);它的输入是c,输出是f;
有一个元件叫U3,是一个两输入或门;它的输入是e和f,输出是y。
通过这个方法,就把电路中有哪些元件,它们分别叫什么名字,它们之间的连接关系是什么详细介绍清楚了。这个方法的核心在于描述“连接关系”和“电路结构”。所以这种方法叫“结构化模型(Structural Modeling)”。
换成硬件描述语言应该这么写:
module example (a, b, c, y);
input a,b,c;
output y;
and U1 (e, a, b);
not U2 (f,c);
or U3 (y, e, f);
endmodule
描述的主体部分采用了一种叫做“例化”的语法。这个语法具体的用法后面会详细的讲解。简单的说就是先说这个元件是一个什么类型的元件,如果是与门,就是and。然后说这个元件叫什么,接下来在括号里面写出对于的端口名称。第一个为输出端口,后面的为输入端口。具体的端口位置和这个元件的最原始声明有关系,在后续的文章中会详解。总之,以上的这段代码就完全按照我们上面说的“人话”,以硬件描述语言规定的语法把电路图2说清楚了。
用以上的方法固然可以把电路图说清楚,但是在很多时候这样说话过于繁琐了。我们完全可以换一种说话的方法。比如我们可以把图1抽象成为一个逻辑表达式:
y=(a&b)|!c
或者我们用人话说y等于a与b的值与c取反后的值相或。这种直接用输入与输出之间的逻辑表达式来描述的方法我们叫“数据流模型(dataflow modeling)”。
module example (a, b, c, y);
input a,b,c;
output y;
assign y=(a&b)|(~c);
endmodule
描述的时候使用了关键字assign,表示这是一种连续赋值。只要等式的右边一变化立刻引起左边y的变化。在等式的右边直接有各种操作符描述了逻辑表达式。&表示与,|表示或,而~表示取反。这样通过一个逻辑表达式我们就直观的描述了输入和输出的关系。这种方式相比与方式1的好处是简单明了。但是这种方式也有缺陷,就是我们需要很明确的指导输入输出之间的逻辑关系。当逻辑比较复杂的时候,我们就很难直接写出这种表达式。所以这个时候我们就需要寻求第三种方法来描述。
当我们很难直接说出一个硬件电路输入和输出之间的逻辑关系的时候,我们可以用一种很“笨”但是很有效的方法来描述电路。就是列举输出和输出之间的关系。真值表就是这样一种描述输出输出关系的方法。
对于图1,我们可以得到这样一张真值表:
图3 图1电路图对应的真值表
这时候我们就知道了abc分别为什么的时候,y应该输出什么值。那么“人话”就可以这样说:当abc为000的时候,y的值为1;当abc为001的时候,y的值为0……
那么可以这样来写代码:
module example (a, b, c, y);
input a,b,c;
output y;
reg y;
always @ (a or b or c )
begin :
case( {a, b,c} )
3'b000 : y= 1'b0;
3'b001 : y = 1'b1;
3'b010 : y = 1'b0;
3'b011 : y = 1'b1;
3'b100 : y = 1'b0;
3'b101 : y = 1'b1;
3'b110 : y = 1'b1;
3'b111 : y = 1'b1;
endcase
end
endmodule
我们可以看在这个例子中,用第三种方法来描述电路要比第二种方法复杂。但如果电路的逻辑功能更复杂的时候,用第三种方法就非常的合适的。如果我们不是采用真值表的方式,而是采用“功能表”的方式。那用第三种方法就更加适合。
图4 74LS194功能表
由于第三种方法实际上是在描述输入的“行为”引起输出“行为”的变化。这种描述方法也被称为“行为模型(Behavior Modeling)”。
以上就是对三种描述数字电路与系统的方法的一点简单的小结。三种描述方式对应了数字电路与系统的三种表现形式:原理图、逻辑表达式、真值表/功能表。硬件描述语言无法是用代码的形式按照语言的规范把这三种形式表达出来而已。
其实归根到底,学会“说话”就学会了如何使用硬件描述语言来描述电路。当年著名诗人白居易(字乐天)每作一首诗,就念给老年妇女听,不懂就改,力求做到她们能懂。因此留下了老妪能解的成语和佳话。其实以现在EDA软件的“智能”水平,还真不一定有没文化的老大妈的智力高。所以各位初学硬件描述语言和数字电路与系统设计的朋友们,可以试试用我们上面采取的“说人话”的方式把整个电路讲给你不懂电子技术的基友(划掉)朋友/同学甚至是父母听。他们明白了你在说什么以后,回过头再去写代码。思路就清晰多了。
END
知乎:https://zhuanlan.zhihu.com/p/51477553
推荐阅读
更多内容请关注其实我是老莫的网络书场专栏