今天先抛开FPGA,单独的从Verilog角度去做一个实战,使用的例子是译码器,从两种不同的思维方式实现不同的译码器,通过RTL电路体会不同逻辑思维对实际电路的影响,印证Verilog硬件描述语言是不同于软件编程语言的,前者会改变硬件电路的状态。
首先,数字电路的设计分为,需求理解分析-代码实现-仿真测试-产品实测(fpga验证),一般的项目实现,会先基于FPGA进行验证,再转移到ASIC中去,若跳过FPGA直接流片,也不是不可以,就可能会影响成本控制。
今天要实现的是一个译码器功能的电路,什么是译码器,个人理解就是输入状态和输出状态有着一一对应的关系,而这些一一对应的关系,是我们提前设计规划好的,如:输入1输出兔子,输入2输出大象等等,每一个不同的输入值,都有一个确定的输出值入职一一对应,有点感觉像中学刚开始学函数时的理解。
译码器:
第一步:分析需求
首先我们需要知道我们要的是什么。首先我们需要一个三八译码器,即三路输入,八个状态(2的三次方),为变量译码器(n-2的n次译码器,代表n个输入,2的n次方个输出)。
明确需求后,开始进行设计:
第一步,建立该功能的文件夹,用来存放译码器的说明文档,工程文件,代码文件,仿真文件等等
第二步,绘制波形图:
建立一个visio文件
流程图如下:
接下来绘制真值表,也就是输入输出的一一对应关系:
开始编写代码,先创建一个.v文件,命名为decoder.v,代码如下:
(一)第一种代码实现方式If-else型:
module decoder
(
input wire in_1,
input wire in_2,
input wire in_3,
output reg [7:0] out
);
always@(*)
if({in_1,in_2,in_3} == 3'b000)
out = 8'b0000_0001;
else if({in_1,in_2,in_3} == 3'b001)
out = 8'b0000_0010;
else if({in_1,in_2,in_3} == 3'b010)
out = 8'b0000_0100;
else if({in_1,in_2,in_3} == 3'b011)
out = 8'b0000_1000;
else if({in_1,in_2,in_3} == 3'b100)
out = 8'b0001_0000;
else if({in_1,in_2,in_3} == 3'b101)
out = 8'b0010_0000;
else if({in_1,in_2,in_3} == 3'b110)
out = 8'b0100_0000;
else if({in_1,in_2,in_3} == 3'b111)
out = 8'b1000_0000;
else
out = 8'b0000_0001;
endmodule
接下来,打开Quartus Ⅱ,创建新的工程文件,Quartus Ⅱ是Altera公司推出的综合性CPLD/FPGA开发软件,软件支持原理图、VHDL、VerilogHDL以及AHDL(Altera Hardware 支持Description Language)等多种设计输入形式,内嵌自有的综合器以及仿真器,可以完成从设计输入到硬件配置的完整PLD设计流程。下载及激活自行百度,资源很多。
Next直到选择FPGA型号,我们根据自身的芯片型号选择,我这里选的是英特尔公司的Cyclone Ⅳ E系列,256pin 芯片名是:EP4CE6F17C8。然后Next,选择仿真软件和语言,我这里选择的是 Modelsim软件和Verilog 语言
接着确认自己所选参数是否正确:
Finish,成功创建,如下图:
点到File层级,开始添加文件
右键File,出现上述字符,点击添加
成功后如下图所示
OK,接下来进行编译,验证是否存在ERROR
编译中:
编译完成,发现没有错误只有警告,可以暂时先不用处理
这个时候,我们查看RTL图:
结果如下:
由七个多路选择器和八个比较器组成,从元器件数量上看,这样实现是比较浪费资源的 。
(二)第二种实现方法,也是比较常用的方法,case型:
先上代码:
module decoder
(
input wire in_1,
input wire in_2,
input wire in_3,
output reg [7:0] out
);
always@(*)
case({in_1,in_2,in_3})
3'b000:out=8'b0000_0001;
3'b001:out=8'b0000_0010;
3'b010:out=8'b0000_0100;
3'b011:out=8'b0000_1000;
3'b100:out=8'b0001_0000;
3'b101:out=8'b0010_0000;
3'b110:out=8'b0100_0000;
3'b111:out=8'b1000_0000;
default:out=8'b0000_0001;
endcase
endmodule
注意:一定要有default默认状态,否则会出现意想不到的情况,如latch等。
现在再查看RTL图:
很明显,我们的代码被综合成了一个译码器,这就是我么今天的实战要实现的东西。三输入八输出的译码器。
接下来,我们进行仿真文件的编写。验证该设计是否有效合理。
创建文件tb_decoder.v文件: