Hello FPGA! 数字电路的基础知识
1、编码
所谓编码,就是以若干二进制数表示一个十进制,这种二进制编码称为二进制编码的十进制数,简称二-十进制编码,也可以称为BCD码(Binary Coded Decimal)。
2、逻辑代数中的三种最基本的逻辑运算:与、或、非。其余都是其组合延伸。
3、硬件描述语言
在FPGA的设计中,我们有多种设计方式,如绘制原理图、编写描述语言代码等。早期的工程师对原理图的设计方式情有独钟,这种输入方式能够很直观的看出电路的结构并快速理解电路。随着逻辑规模的不断攀升,逻辑电路也越来越复杂,这种输入方式就会显得力不从心,应付简单的逻辑电路还算实用,应付起复杂的逻辑电路就不行了。因而取而代之的便是编写描述语言代码的方式,现今的绝大多数设计都是采用代码来完成的。目前主流的硬件描述语言有两种:一种是VHDL,另一种是Verilog。VHDL发展较早,语法严谨;Verilog类似C语言,语法风格比较自由。对于初入FPGA的新手而言,掌握一种硬件描述语言是必要的。
若你之前有一定的C语言基础,那么不妨先学Verilog硬件描述语言,这有助于加快对语言本身的理解。在将其中一门语言学精、用熟之后,最好也能够着手掌握另一门语言;如果没有C语言基础但是你想快速入门,还是先学Verilog。因为VHDL硬件描述语言比较难,不容易学习,而Verilog硬件描述语言则相对比较容易学习,能够快速入门。
4、Verilog语法结构
模块是Verilog HDL的基本描述单位,用于描述每个设计的功能或结构,以及与其他模块通信的外部接口。一个模块可以包括整个设计模块或者设计模型的一部分,模块的定义总是以关键词module开始,以关键词endmodule结尾。
1)“模块名”是模块唯一的标识符,括号中以逗号分隔列出的端口名是该模块的输入、输出端口。
2)“端口类型说明”为input(输入)、output(输出)、inout(双向端口)三种类型,凡是在模块名后面圆括号中出现的端口名都必须明确地说明其端口类型。
3)“参数定义”是将常量用符号常量代替,以增加程序的可读性和可修改性,它是一个可选择的语句,用不到可以省略。
4)“数据类型定义”部分用来制定模块内所用的数据对象是寄存器类型(reg等)还是连线类型(wire等)。
5)剩下的三个语法为:实例引用低层次模块和基本门级元件、连续赋值语句和过程块描述,这里不作介绍。
5、与门电路的Verilog代码
代码中没有数据类型定义,是因为input或者output默认的数据类型是wire型,所以我们将数据类型定义给省去了。当然我们可以给它们再一次定义,比如:wire A, wire B, wire Y; 这里需要注意,input类型只能是wire,我们一般对input类型不做任何数据类型定义。
代码中用的是连续赋值语句assign,赋值语句assign是针对wire型变量的一种赋值语句,wire型变量一般对应到FPGA中的一根线,由于wire型的值是会随着驱动源的变化而变化的,所以我们也将assign称为“连续”赋值语句。
Verilog中只有三种最基本的逻辑运算,与(&&)、或(||)、非(!)。
以下给出的是引用低层次模块的基本门级元件:
Verilog HDL内置26个基本元件,其中14个是门级元件,12个为开关级元件,这里只介绍7个基本门,and(与)、nand(与非)、or(或)、nor(或非)、not(非)、xor(异或)、nxor(同或)。
以下给出的是过程块描述方法:
在Verilog 中,任何过程赋值的左侧变量必须声明为reg,除此之外使用的变量必须声明为wire,没有其他例外的情况。那么在Verilog 中为什么要区分reg和wire类型呢?这个问题的答案和数据类型检查有关。如果有人尝试对同一个变量既做连续赋值,又做过程赋值,那么连续赋值要求用wire声明,过程赋值要求用reg声明,但是把同一个变量同时声明为两种类型,就是语法错误,这就保证了设计者不能用同一变量使用两种不同类型赋值。
always@(A,B):@是事件等待语句,意思是always不断循环等待A和B两个敏感变量变化,不管A和B是从高到低,还是从低到高,都将会执行always下面的Y=A&&B语句。如果A和B都没有变化,那么always将不往下执行,一直循环等待。新标准也可以这样写:always @(*),这是一个组合逻辑电路的描述方式,是为了防止你在设计时考虑不周全带来一些操作失误,所以敏感表用*(*表示全部的敏感变量),只要有任何输入信号变化,其输出立即发送变化。
6、Verilog HDL是硬件描述语言
它为什么是描述而不是设计呢?其主要原因就是硬件描述语言确实不是用来设计电路的,而仅仅是用来描述电路的。描述这词,精确地反映了硬件描述语言的本质。我们在写Verilog 代码的时候,大脑里要先想好完成的具体功能应该用什么样的物理电路去实现,然后用Verilog 语言将该电路描述出来,而不能凭空地去写代码,只有存在的电路才是可物理实现的,Verilog 语言只不过是将这种设计转化为文字表达形式而已。
秋招“笔试经”第三弹:华为硬件逻辑岗
接上一次华为题的2道,接下来是第3、4道:
3、只读存储器ROM中的内容,当电源断掉后又接通,存储器中的内容 ( )。(华为硬件逻辑实习岗)
A 全部为0 B 不可预料
C 保持不变 D 全部改变
解析:考察数字电路中存储器的基本知识
下图所示为常见存储器件的性质关系:
1)易失性存储器的代表就是RAM,RAM又分为DRAM(动态随机存储器)和SRAM(静态随机存储器),它们之间主要在于生产工艺不同。
SRAM保存数据是通过晶体管进行锁存的,其工艺复杂,生产成本高,所以价格相对较贵,不易做大容量,但是速度更快;DRAM保存数据靠电容充电来维持容量,生产成本较SRAM低,所以价格相对便宜,容量可以做到很大,速度虽然不如SRAM快但是随着工艺技术的提升,速度也很可观,所以较为常用。DRAM和SRAM都是异步通信的,速率没有SDRAM(同步动态随机存储器)和SSRAM(同步静态随机存储器)快。所以现在大容量RAM存储器是选用SDRAM的。
CPU中的Cache实质属于SRAM,而内存条则是属于DRAM。SDRAM和DDR SDRAM的区别在于DDR(Double Data Rate)是双倍速率。SDRAM只在时钟的上升沿表示一个数据,而DDR SDRAM能在上升沿和下降沿都表示一个数据。DDR也一步步经过改良出现了一代、二代、三代、四代,以及低功耗版本,现在也有五代。
2)非易失性存储器常见的有ROM,FLASH,光盘,软盘,硬盘。他们作用相同,只是实现工艺不一样。
ROM(Read Only Memory)在以前就是只读存储器,就是说这种存储器只能读取它里面的数据无法向里面写数据。实际是以前向存储器写数据不容易,所以这种存储器就是厂家造好了写入数据,后面不能再次修改。现在技术成熟了,ROM也可以写数据,但是名字保留了下来。ROM分为MASK ROM、OTPROM、EPROM、EEPROM。MASK ROM是掩膜ROM这种ROM是一旦厂家生产出来,使用者无法再更改里面的数据。OTPROM(One TimeProgramable ROM)一次可变成存储器,出厂后用户只能写一次数据,然后再也不能修改了,一般做存储密钥。EPROM(Easerable Programable ROM)这种存储器就可以多次擦除然后多次写入了。但是要在特定环境紫外线下擦除,所以这种存储器也不方便写入。EEPROM(Eelectrically Easerable Programable ROM)电可擦除ROM,现在使用的比较多因为只要有电就可擦除数据,就可以写入数据。
FLASH是一种可以写入和读取的存储器,叫闪存,FLASH也叫FLASH ROM,有人把FLASH当做ROM。FLASH和EEPROM相比,FLASH的存储容量大。FLASH的速度比现在的机械硬盘速度快,现在的U盘和SSD固态硬盘都是Nandflash。FLASH又分为Norflash和Nandflash。
综上所述,本题答案选C 保持不变。
4、在Verilog语言中,a = 4’b1011,那么&a为( )。(华为硬件逻辑实习岗)
A 4’b1111 B 1’b1
C 1’b0 D 4’b1011
解析:考察Verilog基本语法中的操作符
“&”操作符有两种用途,既可以作为一元操作符(仅有一个操作数),也可以作为二元操作符(有两个操作数)。
当“&”作为一元操作符时表示归约与。&m是将m中所有比特相与,最后的结果为1bit。例:&4‘b1111 = 1&1&1&1 = 1’b1,&4’b1101 = 1&1&0&1 = 1’b0。
当“&”作为二元操作符时表示按位与。m&n是将m的每个比特与n的相应比特相与,在运算的时候要保证m和n的比特数相等,最后的结果和m(n)的比特数相同。例:4’b1010&4’b0101 = 4’b0000,4’b1101&4’b1111= 4’b1101。
我们在写Verilog代码时常常当if的条件有多个同时满足时就执行使用“&&”逻辑与操作符。m &&n是判断m和n是否都为真,最后的结果只有1bit,如果都为真则输出1‘b1,如果不都为真则输出1’b0。要注意和“&”的功能区分。
此外“&”操作符作为归约与使用时还有妙用。下面是一个分频器,代码结构简单,逻辑也不复杂,就是当计数器计数到15时让输出out取反,相当于实现对sclk的32分频。
//--------------------------------------------------
01module divider(
02 input wire sclk ,
03 input wire rst_n ,
04
05 outputreg out
06);
07
08reg[ 3: 0] cnt;
09
10//cnt
11always@(posedge sclk ornegedge rst_n)
12 if( rst_n == 1'b0)
13 cnt <= 4'b0;
14 else if( cnt == 4'd15)
15 cnt <= 4'b0;
16 else
17 cnt <= cnt + 1'b1;
18
19//out
20always@(posedge sclk ornegedge rst_n)
21 if( rst_n == 1'b0)
22 out <= 1'b0;
23 else if( cnt == 4'd15)
24 out <=~ out;
25
26endmodule
//--------------------------------------------------
我们可以看到第14行和第23行都使用了一个判断语句,是判断计数器cnt是否达到15,如果达到是计数器清零,且输出out取反。我们比较器要将cnt的每一个比特都和4‘d15的每一位进行比较,也就是判断(cnt== 4’b1111),会浪费更多的资源。而我们今天想到了“&”的用法就可以实现妙用,我们将判断条件改为(&cnt == 1‘b1),当计数器计数到15时,即所有的比特都为变为了1,那么&cnt为1‘b1,而其余情况&cnt都为1’b0,这样比较的位数就只有1位了,节省了资源。希望大家以后遇到此类相关情况推荐使用“&cnt”的方法。
注:如果大家在使用QuartusII工具进行验证上面的结论,想看看是否真的会节约逻辑资源时,可能看不到想要的结果,这是因为当描述的系统不复杂时综合器能够比较好的对逻辑进行优化(证明被优化的结果可以通过RTL视图定位在Chip Planner中的位置得到验证),而当描述的系统较为复杂时就不能够保证综合器能够有比较好的优化效果,或许以后综合器可以变得更加智能,但是目前还是使用推荐的写法更稳妥。
综上所述,本题答案选C 1‘b0
作业:下一期我们将对下面的题目进行详细的扩展解析,大家可以提前做一下,敬请期待……
5、下面哪种不是组合逻辑电路功能描述方法( )。(华为硬件逻辑实习岗)
A 真值表 B布尔方程 C状态机 D逻辑框图
6、时序电路的一般特征不包括( )。(华为硬件逻辑实习岗)
A 系统的状态保持或者变化情形取决于系统的输入及其当前状态
B 时序机的状态图和状态表是相同的设计信息的两种不同的表示形式
C 可以没有时钟
D 时序电路(机)的当前状态和输入信号决定了其下一状态及输出
(转自达尔闻说)
相关问答
verilog 怎么定义和调用d触发器?直接根据D触发器结构描述就好了嘛moduleD_FF(CLK,D,Q,Q_);inputCLK,D;outputQ,Q_;wirew1,w2;nand(w1,CLK,D);nand(w2,...