FPGA系统性学习笔记连载_Day6 FPGA三种建模方式区别及Verilog语法基础篇
本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主。
连载《叁芯智能fpga设计与研发-第6天》 【FPGA数据流建模、行为级建模、结构化建模 区别】及【Verilog HDL语法基础】
原创作者:紫枫术河 转载请联系群主授权,否则追究责任
这篇文件记录,FPGA的3种建模方式及基本的Verilog HDL语法,内容会根据学习进度,不断更新。
一、FPGA的3种建模方式
A、数据流建模(assign)
在数字电路中,信号经过组合逻辑时会类似于数据流动,即信号从输入流向输出,并不会在其中存储。当输入变化时,总会在一定时间以后体现在输出端。同样,我们可以模拟数字电路的这一特性,对其进行建模,这种建模方式通常被称为数据流建模。
1.1、是使用连续赋值语句(assign)对电路的逻辑功能进行描述,该方式特别便于对组合逻辑电路建模
1.2、连续驱动,连续赋值语句是连续驱动的,也就是说只要输入发生变化,都会导致该语句的重新计算。
1.3、只有线网型的变量才能在assign语句中被赋值
1.4、因为assign语句中被赋值的变量,在仿真器中不会存储其值,所以该变量必须是线网(Nets)类型,不能是寄存器(reg)类型
1.5、线网类型的变量,可以被多重驱动,也就是说可以在多个assign语句中驱动同一个net
1.6、reg型变量,不能被不同的行为进程(eg:always块)驱动
1.7、建议使用assign对组合逻辑建模,这是因为assign语句的连续驱动特点与组合逻辑的行为非常相似,而且在assign语句中加延时可以非常精确地模拟组合逻辑的惯性延时。
1.8、assign语句与行为语句块(always和initial)、其它连续赋值语句、门级模型之间是并行的。
一个连续赋值语句是一个独立的进程,进程之间是并发的,同时也是交织的。
B、行为级建模(initial、always)
行为方式的建模是指采用对信号行为级的描述(不是结构级的描述)的方法来建模。
在表示方面,类似数据流的建模方式,但一般是把用initial 块语句或always 块语句描述的归为行为建模方式。
行为建模方式通常需要借助一些行为级的运算符如加法运算符( ),减法运算符(-)等。
需要先建立以下概念:
- 2.1、只有寄存器(reg)类型的信号才可以在always和initial 语句中进行赋值,类型定义通过reg语句实现。
- 2.2、always 语句是一直重复执行,由敏感表(always 语句括号内的变量)中的变量触发。
- 2.3、always 语句从0 时刻开始。
- 2.4、在begin 和end 之间的语句是顺序执行,属于串行语句。
C、结构化描述(反映了一个设计的层次结构)
结构化描述就是说在设计中实例化已有的功能模块,这些功能模块包括门原语、用户自定义原语(UDP)和其他模块(module)。
以下是结构化描述的3种实例类型:
- 3.1、实例化其他模块
- 3.2、实例化门(如与门and、异或门xor等)
- 3.3、实例化UDP
二、RTL级、Behavior级
RTL级,register transfer level,指的是用寄存器这一级别的描述方式来描述电路的数据流方式;
Behavior级,(行为级)指的是仅仅描述电路的功能而可以采用任何verilog语法的描述方式。
2种方式的区别:
1、目的区别:
行为级描述:目的是加快仿真速度,做法是尽量减少一个always块中要执行的语句数量,其结果不是为了综合,只关注算法。
有行为综合工具,可以直接将行为级的描述综合为RTL级的,比如Behavioral Compiler。
2、形式区别:
RTL级描述:
- 目的是为了综合工具能够正确的识别而编写的代码,verilog中有一个可综合的子集,不同的综合工具支持的也有所不同;
- RTL级的描述就会更详细一些,并且从寄存器的角度,把数据的处理过程表达出来。可以容易地被综合工具综合成电路的形式。
- 可以采用任何verilog语法 的描述方式。鉴于这个区别,RTL级描述的目标就是可综合。
行为级描述:
更多的是采取直接赋值的形式,只能看出结果,看不出数据流的实际处理过程。其中又大量采用算术运算,延迟等一些无法综合的语句。常常只用于验证仿真。
3、电路区别:
RTL级,register transfer level
指的是用寄存器这一级别的描述方式来描述电路的数据流方式;RTL在很大程度上是对流水线原理图的描述。哪里是组合逻辑,哪里是寄存器,设计者应该了然于胸。
组合逻辑到底如何实现,取决于综合器和限制条件。RTL是晶体管传输级,描述硬件的相互联接关系,一般都可以综合;
Behavior级
指的是仅仅描述电路的功能而在硬件设计中有一句著名的话:thinking of hardware。 简单说,rtl就是用寄存器和组合逻辑组成,不能再用其他construct; behavior就是指定输入和输出之间的关系
4、 同样是for语句,如果循环条件是常数,就是RTL的,如果是变量,就是behavior的。
三、verilog语法基础
1、信号的类别
输入 :input
输出 :output
输入输出 :inout
2、内部信号
寄存器信号(时序逻辑)reg oe;
线网型信号(组合逻辑) wire oe;
3、端口的位宽的类别
位宽为8的输入信号 input [7:0] data
4、连续赋值语句
将右边的值赋值给左边 assign out = sel?a:b;
5、在assign语句中被赋值了的变量,都要申明为 wire类型
代码语言:javascript复制module and_gate (
input wire [3:0] a,
input wire [1:0] b,
output wire s
);
assign s = &a;
endmodule
6、在initial、always语句中被赋值了的变量,都要申明为 reg类型
代码语言:javascript复制module and_gate_tb;
reg tb_a;
reg tb_b;
initial begin
tb_a = 1;
tb_b = 1;
end
endmodule
7、always语法
1>、always @ (posedge clk,negedge rst_n) begin----end
always:表示总是的意思;
@:表示等到的意思;
(posedge clk,negedge rst_n):括号代表对什么敏感,这里就是对时钟上升沿或者rst_n的下降沿敏感;
逗号:或的意思,可以写成 or
注:这句话的意思是,等到 clk的上升沿 或 rst_n下降沿到了,就执行 begin----end之间的语句
代码语言:javascript复制always @ (posedge clk,negedge rst_n) begin //异步复位,跟时钟无关
if(rst_n == 0)
q <= 0;
else
q <= q 1'b1;
end
always @ (posedge clk or negedge rst_n) begin //异步复位,跟时钟无关
if(rst_n == 0)
q <= 0;
else
q <= q 1'b1;
end
2>、always @ (*) begin---end
(*):代表本always块用到的所有变量,综合工具和仿真工具,会自动将本always块,使用到的所有的敏感信号加入敏感信号列表,当敏感信号状态发生改变,就执行begin--end中的语句
代码语言:javascript复制always @ (*) begin
casex (din)
8'b0000_0001 : bin = 3'b000;
8'b0000_0010 : bin = 3'b001;
8'b0000_0100 : bin = 3'b010;
8'b0000_1000 : bin = 3'b011;
8'b0001_0001 : bin = 3'b100;
8'b0010_0001 : bin = 3'b101;
8'b0100_0001 : bin = 3'b110;
8'b1000_0000 : bin = 3'b111;
default : bin = 3'b000;
endcase
end
3>、case语法
代码语言:javascript复制always @ (*) begin
casex (din)
8'b0000_0001 : bin = 3'b000;
8'b0000_0010 : bin = 3'b001;
8'b0000_0100 : bin = 3'b010;
8'b0000_1000 : bin = 3'b011;
8'b0001_0001 : bin = 3'b100;
8'b0010_0001 : bin = 3'b101;
8'b0100_0001 : bin = 3'b110;
8'b1000_0000 : bin = 3'b111;
default : bin = 3'b000;
endcase
end
4>、casex语法
casex -- endcase: 成对出现,注意 以下b1xxx_xxxx的写法,是简化写法,1后面的x代表值是随机的不关心的;
例如 8b1xxx_xxxx = 8b1000_1111/8b10101_1010,8b0xxx_xxxx=8b0000_0000/8b01010_0101
代码语言:javascript复制always @ (*) begin
casex (din)
8'b1xxx_xxxx : bin = 3'b111;
8'b01xx_xxxx : bin = 3'b110;
8'b001x_xxxx : bin = 3'b101;
8'b0001_xxxx : bin = 3'b100;
8'b0000_1xxx : bin = 3'b011;
8'b0000_01xx : bin = 3'b010;
8'b0000_001x : bin = 3'b001;
8'b0000_0001 : bin = 3'b000;
default : bin = 3'b000;
endcase
end
5>、repeat语法
代码语言:javascript复制initial begin
repeat(15) begin
din = {$random}%6;
#20;
end
end
6>、位拼接
代码语言:javascript复制wire [7:0] A;
wire B;
wire C;
wire [1:0] D;
B = A[7];
C = A[6];
D = (B,C);
D = A[7:6];
7>、仿真文件,首先要定义时间精度,因为延时语句以这个作为时间刻度,#代表延时标记
1ns是周期,1ps是精度
注:延时语句是非综合语句,是不能形成电路的
代码语言:javascript复制`timescale 1ns/1ps
module and_gate_tb;
reg [1:0] tb_a;
reg [1:0] tb_b;
and_gate and_gate_inst(
.a (tb_a),
.b (tb_b),
.s ()
);
initial begin
tb_a = 2'b00;
tb_b = 2'b00;
#20;
tb_a = 2'b01;
tb_b = 2'b10;
end
endmodule
【QQ交流群】
群号:173560979,进群暗语:FPGA技术江湖粉丝。
多年的FPGA企业开发经验,各种通俗易懂的学习资料以及学习方法,浓厚的交流学习氛围,QQ群目前已有1000多名志同道合的小伙伴,无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有。
【微信交流群】
现微信交流群已建立09群,人数已达数千人,欢迎关注“FPGA技术江湖”微信公众号,可获取进群方式。
完
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
江湖偌大,继续闯荡,愿大侠一切安好,有缘再见!