数字电路基础复习
结合Verilog回顾,一并复习基础的数字电路设计
verilog的本质是硬件描述语言,而不是硬件设计语言。
Syntax Explanation:
1 | module |
例一:
tip:声明变量中,位宽的表示:从左到右依次为高位到低位,代表位宽为4的输入和输出端口。
1 | module gates( |
例二:八输入与门
tip:
- 单独输出多位宽信号的一位或者多位的时候可以以这种方式单独处理,即a[7]
- &:按位与、归并与操作,如该操作符只有一个操作数的时候,则该操作数的所有位进行相与操作,可以实现注释部分相同的功能,但写法更简洁。
1 | module and8( |
例三:一位全加器,同时还有半加器。
tip: 该部分内容在NJU数电计组教程第145页
1.
不考虑低位进位,仅考虑两个加数的一位编码器称为半加器,反之考虑低位进位的就叫全加器。
以下是半加器的真值表:其中A,B分别为代加的数据,Cout和F分别是进位和加和
1 | A | B | F | Cout |
可以设计这样的半加器verilog代码:
1 | module HA( |
1 | 1bit-FA(cout,s) = a + b + cin; |
一位全加器的真值表如下所示:
1 | A | B | Cin|S |Cout |
- wire: wire是线网型数据类型,verilog语法中的一种主要数据类型,用于表示线网型信号,与实际电路中的信号连线相对应。wire是verilog中的默认数据类型,此例中的输入输出信号没有指定数据类型,则默认为wire型。除wire外,另一种主要的数据类型为reg,表示寄存器类型数据。
1 | module FA( |
例四:三态门
tip:
- z表示高阻态,在verilog中,信号有四种状态。0、1、x、z,分别表示低电平、高电平、不确定态和高阻态。对于没有进行初始化的信号,一般处于不确定态(x),高阻态表示该信号没有被其他信号驱动,经常用于有多个驱动源的总线型数据上。
- 4’bz: 数据格式,表示该信号为4 bit位宽,用二进制的方式表示。
1 | module tristate( |
例五:八位二路选择器
tip:
模块例化(Model Instancilization): 可以通过实例化已经设计好的模块来达到重用模块,简化设计的目的。可以将一个模块重用多次,在同一模块中,实例化名称(本例中为lsbmux, msbmux)可任意指定,但不能相同,也不能使用verilog中的关键字。本例这种列举了verilog语法支持的两种实例化方式,推荐使用第二种方式,虽然代码量增加了一些,但增加了可读性,同时降低了出错的风险。
对于第一种模块例化方法,应严格保证实例化模块lsbmux中的参数排列顺序与被实例化模块mux2的参数排列顺序严格一致。
对于第二种模块例化方法,.点后面是被例化模块mux2的接口信号,括号内的是实例化模块(msbmux)的接口信号。
1
assign y = {a[2:1], {3{b[0]}}, a[0], 6'b100_010};
位拼接:可将一个或多个信号的指定位,拼接成一个新的信号,对于上述表达式,如果y是一个12bit的信号,则各位的值分别是:
1 | a[2],a[1],b[0],b[0],b[0],a[0],1,0,0,0,1,0 |
下面是verilog代码:
1 | module mux2( |
例五:D触发器
tip:
- 时序逻辑:电路具有记忆功能,电路状态不但与当前输入有关,还与前一时刻的状态有关。
- D锁存器:D锁存器只有一个状态驱动信号D,有一个D锁存器使能信号en。若en=1,则此时D锁存器或存储当前状态驱动信号输入的值;而若en=0,则此时D信号无法改变其状态,也即输出Q存储了上一次存储的D状态驱动信号。
- D触发器:与D锁存器不同的是,D触发器通过采用时钟边沿触发机制,来提高状态的稳定性。可以通过两个D锁存器用主从的方式来构造。
- 同步逻辑:在统一的时钟信号激励下工作,输出只在时钟的上升沿(或者下降沿)发生变化。
- reg: 除wire类型外,还有另一种常用的数据类型,一般表示寄存器类型数据,不过并不绝对。记住一条原则,在always块内被赋值的信号应定义成reg型,在assign语句中赋值的信号应定义成wire型。
- always块:除了assign外,还有另外一种·实现赋值操作的关键字,两者都不可嵌套,区别在于assign只能实现组合逻辑赋值,且一个assign语句后面只能跟一条赋值表达式,而always可以实现组合逻辑赋值,而且也能实现时序逻辑赋值操作。并且它可以包含多条赋值表达式,位于begin/end对中间。
1 | always @(*) //@(*)的意思是在任何信号发生改变的时候都执行如下的内容,可以简单理解为这样的always块是在构造组合逻辑电路。 |
- posedge: verilog关键字,表示上升沿的意思。always@(posedge clk)表示在clk信号的上升沿的时刻,执行always块内部的语句,与此对应的,是表示下降沿的关键字negedge。凡是带有posedge或者negedge的always块,都会被综合成时序逻辑电路。
- 阻塞/非阻塞赋值:采用“<=”进行赋值的语句,称为非阻塞赋值,采用”=”等号进行赋值的语句,成为阻塞赋值。在always块中,阻塞式赋值方式语句执行有先后顺序,而非阻塞语句则是同时执行·。因此,在时序逻辑电路中,两种赋值方式可能或综合处不同的电路结构.
- 一些很重要的编写verilog代码的规则:
(1)在组合逻辑电路中,使用阻塞式赋值方式”=”;在时序逻辑电路中,使用非阻塞式赋值方式”<=”
(2)在同一个always块中,只能存在一种赋值方式。
(3)一个信号,只能在一个always块或一个assign语句下赋值,不可被重复赋值!
(4)原则上来说,一个always块内只处理一个或一类信号,不同的信号可在不同的always块内处理。
(5)always块内只能对reg型信号进行处理,不能对wire型数据赋值,也不能实例化模块。
1 | module flop( |
例六:带同步复位的D触发器
tip:
- 同步复位:复位只能发生在clk信号的上升沿,若clk信号出现问题,则无法进行复位。
- If/else: always块中常用的条件判断语句,可以嵌套,有优先级,一般来说,应将复位处理逻辑放在第一个if语句下,使其拥有最高的优先级,该语句只能在always块中使用。另外一种比较常用的条件判断语句是case,与If/else语句不同,case语句不带优先级。
1 | module flopr( |
例七:异步复位电路
tip:
- 异步复位:在always的敏感变量列表中,包含了posedge clk(clk信号上升沿)和posedge reset(reset信号下降沿)两个条件,只要有一个条件发生,便会执行always块内的逻辑。复位处理程序应具有最高的优先级。
1 | module flopren( |