三、1【Verilog HDL】基础语法快速入门(FPGA开发)

参考资料:

参考野火FPGA开发视频的基础语法:【野火】FPGA系列Xilinx Artix7教学视频,真正的手把手教学,“波形图”教学法,现场画波形图写代码,硬件基于野火FPGA-升腾系列开发板,更新中_哔哩哔哩_bilibili【野火】FPGA系列Xilinx Artix7教学视频,真正的手把手教学,“波形图”教学法,现场画波形图写代码,硬件基于野火FPGA-升腾系列开发板1、配套硬件:https://detail.tmall.com/item.htm?id=6451534419752、硬件介绍:核心板3款,XC7A-35T/100T/200T,底板2款Pro和Mini,3款核心板可分别接到2款底板上3、配套资料:https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=4


基础知识 

逻辑值

0:逻辑低,假; 

1:逻辑高 ,真; 

z:高阻,无驱动,常在对三态门进行建模时使用; 

x:未知逻辑电平,当用作条件判断时(在casex或casez)表示不关心

二进制只有0和1,但是Verilog语言中,为了对电路进行精确建模添加”z“和”x“两种状态(这里z和x不区分大小写)。

常量

类型:整数、实数、字符串

格式:【换算成二进制后位宽的总长度】【’】【进制符号】【与进制符号对应的数值】

格式说明:【位宽的总长度】可有可无,Verilog会自动为常量匹配适合位宽

        【进制符号】【h】十六进制,【o】八进制,【b】二进制,【d】十进制

          8'd171:位宽位8bit,十进制的171

          8'hab:8bit,十六进制数ab

          8'o253:8bit,八进制数253

          8'b1010 1011:8bit,二进制数1010 1011

         当换算后总位宽大于实际位宽则自动左边补0;总位宽小于实际位宽则自动阶段左边超出位数

        例: 'd7与8'd7:换算二进制为8'b0000 0111,左边补5位0

                2'd7:换算二进制为2'b11,超过两位的部分被截断

变量

类型:

1、线网型:表示电路间的物理连接,在可综合的逻辑中会被映射成一条实际的物理连线

2、寄存器型:表示一个抽象的数据存储单元,在可综合逻辑中会映射成真是的物理寄存器,在仿真器中也会占据一个仿真内存空间

类型说明:任何一个变量都会有明确的变量类型。凡是在always或者initial语句中被赋值的变量(赋值号左边的变量),不论表达的组合逻辑还是时序逻辑,一定都是reg(寄存器型);凡是assign语句中被赋值的变量,一定时wire(线网型)。

参数

参数是一种常量,通常出现在模块内部,常常被定义状态机的状态、数据位宽和计数器计数个数大小等。

常用的关键字(保留字)

module:模块声明关键字,其后为模块名(需要和文件保持一致)

endmodule:模块结束声明关键字

注:在模块声明内不能再含有模块声明

input:输入信号

output:输出信号

inout:输入输出信号(如:I^2C中的SDA引脚即可以作为指令输入也可以作为数据的输出)

wire: 线网型变量

reg:寄存器型变量

parameter:参数定义,在顶层文件通过实例化时参数可以修改

localparam:参数定义,在模块内部使用不能进行实例化参数不可以更改

1 module test
2 (
3 
4     input wire sel , /*输入输出控制信号,sel 为 1 时双向数据总线
5                        向外输出数据,sel 为 0 时双向数据总线为高阻态可以向内输入数据*/
6 
7     input wire data_out , /*由内部模块传来要发送给双向数据总线
8                             向外输出的数据*/
9     inout wire data_bus , //双向数据总线
10    output wire data_in /*接收双向数据总线从外部输入的数据后
11                          输出到其他内部模块*/
12 
13 );
14 endmodule

赋值语句

类型:

在begin-end串行

“ = ” 阻塞赋值,串行执行,与c相似从上到下从左到右顺序执行     

“ <=  ”非阻塞型过程赋值,并行执行,赋值语句同时执行,本条语句不会影响下条语句的执行

运算符

算数运算符 

 “+”、“-”、“*”、“/”、“%”

归约运算符、按位运算符

以“&”操作符为例,“~&”、“^”、“~^”、“|”、“~|”同理。有两种用法:

1、作为一元运算符(仅有一个参与运算的量)表示归约与,&m表示m中所有比特位相与,最终结果为1bit。例:&4'b1001 = 1&1&0&1 = 1'b0。

2、作为二元运算符(有两个参与运算的量)表示按位与,m&n表示m与n中相对应的位相与,因此要求m和n的比特位数相同,最终结果和m(n)的比特位数相同。例:2'b01&2'b11 = 2'b01。

逻辑运算符

以“&&”逻辑与操作符为例,“||”逻辑或、“==”逻辑相等、“!=”逻辑不等同理。常用在Verilog中的if、while等条件语句中,来判断条件是否符合,与c语言类似。

“&&”运算规则:判断“&&”两边为真还是假,两边都为真时结果为真(1),否则为假(0)

例:a = 4'ha ,b = 4'd0,c = a&&b,则c的值为假(0)(1'b0)。

关系运算符

“<”、">"、"<="、">="用法和c语言类似,用于if等条件判断,符合时返回值1,否则为0。

移位运算符

移位运算符为二元运算符,“<<”为左移符号;“>>”为右移符号,将运算符左边的操作数左移或者右移运算符右边的指定位数,用0补充空闲位。

    b <=  a<<1;即让a的每一位都往左移动1位,且结果赋值给b;

    b <=  a>>2;即让a的每一位都往右移动2位,且结果赋值给b;

  在应用时注意,移位后空闲位用0来填充,故一个二进制数,只要一直移位,最终都会变为0。

例:4'b1000 >> 3后的结果为4’b0001;但4'b1000>>4后结果位4'b0000。

 移位运算符在使用时,可代替乘法与除法,左移一位可以看成乘2,右移一位可以看成除2,但是要注意数据位宽的拓展,否则会出现移位后全为0的情况。

位拼接运算符 

位拼接运算符表示成一对花括号加逗号组成 “{ , }”,拼接的不同数据之间用“ , ”隔开。

例:将8bit的a、3bit的b、5bit的c按顺序拼接为16位的d,表示:d={a,b,c};

类似于MATLAB中对向量(矩阵)的处理,两个向量进行拼接。

条件运算符

条件运算符为三元运算符,表示成 “ ? :”,例:表达式1?表达式2:表达式3

运算规则:表达式1为真时,则表达式2的值为结果作为返回值,否则表达式3为结果最为返回值。

例:a = 6,b = 7,c = (a>b)?a:b,a>b为假,则将b的值赋给c,最后结果为 c = 7 

运算符的优先级

优先级关系:归约运算符 > 算数运算符 > 移位运算符 > 关系运算符 > "=="和"!=" >  按位运算符 > "&&"和"||" > 条件运算符,总一元运算符 > 二元运算符 > 三元运算符。"()"括号可以改变优先级。

分支语句

if-else条件分支语句

if-else的用法与c语言基本类似,常用推荐写法:

if(<条件表达式 1>)
语句或语句块 1;
else if(<条件表达式 2>)
语句或语句块 2;
………
else

如果在if-else条件语句中没有出现else项只有if,这种写法如果在always块中表达组合逻辑时会产生latch,所以在使用的时候if-elsr要同时出现。

如果在if-else条件语句中嵌套其他if-else条件语句,可以使用,但是不推荐,因为嵌套会出现优先级问题,导致逻辑混乱。

case分支控制语句

一、C、switch(){case: }语句_FPGA-桥的博客-CSDN博客_switch(){case}switch(){case : case :...... }先说语法,再说注意事项switch的判断变量类型只能是字符型或者整型,请注意,只有这两种才可以switch后面紧跟的那个小括号里面就是 要判断的变量名称 然后switch要求它后面的大括号完整,不能不写case 后面加一个空格跟上条件 当然条件也只能是字符型或者整型,然后加上冒号,条件语句正式开始 ,末了,不要忘记分号,然后每个https://blog.csdn.net/ARM_qiao/article/details/77892740类似c语言中的switch-case语句类似,case分支语句多用来实现多路分支控制。由于FPGA本身是并行执行,故与if-else语句(有较多限制,推荐的是按照顺序(串行)执行)相比显得更为方便直观。case分支语句通常用于对微处理器指令译码功能的描述以及对有限状态机的描述。有“case”、“casez”、“casex”三种形式。常用推荐写法:

case(<控制表达式>)
    <分支语句 1> : 语句块 1;
    <分支语句 2> : 语句块 2; 
    <分支语句 3> : 语句块 3;
    ………
    <分支语句 n> : 语句块 n;
    default : 语句块 n+1;
endcase

<控制表达式>:代表对程序流向进行控制的控制信号;

<分支表达式>:则是控制表达式在某些具体状态下的取值,实际使用常用常量或者常量表达式;

语句块:当<控制表达式> == <分支表达式>时,执行语句;

default:<控制表达式>没有对应的<分支表达式>时,执行其后的语句,该分支可以缺省。

注:在执行了某一分支项内部的语句后,跳出case语句结构,终止case语句的执行。case语句中各个“分支表达式项”的取值必须是互不相同的,否则会出现矛盾现象。

系统任务和系统函数

 Verilog语言中预先定义了一些任务和函数,用于完成一些特殊的功能,他们被称为系统任务和系统函数,这些函数大多数都是只能在Testbench仿真中使用,方便进行验证。

时间尺度预编译指令

`timescale 1ns / 1ns // 时间尺度预编译指令 时间单位 / 时间精度
时间单位和时间精度由值 1 10 、和 100 以及单位 s ms us ns ps fs 组成。
时间单位:定义仿真过程所有与时间相关量的单位。
仿真中使用 # 数字 表示延时相应时间单位的时间,例 # 10 表示延时 10 个单位的时间,
10ns
时间精度:决定时间相关量的精度及仿真显示的最小刻度。
`timescale 1ns / 10ps 精度 0.01 # 10.11 表示延时 10110ps
下面这种写法就是错误的,因为时间单位不能比时间精度小。
`timescale 100ps / 1ns

仿真中常用的系统函数

仿真中主要的系统函数如下,在Verilog语法的编辑中会显示为高亮关键字

$display //打印信息,自动换行
$write // 打印信息
$strobe // 打印信息,自动换行,最后执行
$monitor // 监测变量
$stop // 暂停仿真
$finish // 结束仿真
$time // 时间函数
$random // 随机函数
$readmemb // 读文件函数

以下将分别介绍以上系统函数

1、$display 用于输出、打印信息

$display("%b+%b=%d",a, b, c);//格式“%b+%b=%d” 格式控制,未指定时默认十进制

% h % H // 以十六进制的形式输出
% d % D // 以十进制的形式输出
% o % O // 以八进制的形式输出
% b % B // 以二进制的形式输出
1 //a,b,c 输出列表,需要输出信息的变量
2 //每次打印信息后自动换行
3 `timescale 1ns/1ns                 /*定义时间尺度*/
4 
5 module tb_test(); 
6 
7     reg [3:0] a;                  /*声明一个a为4bit的寄存器变量*/
8     reg [3:0] b;
9     reg [3:0] c;
10 
11     initial begin                  /*initial只在仿真文件中使用,不可综合的*/             
12         $display("Hello");         /*打印信息*/
13         $display("EmbedFire");
14         a = 4'd5; 
15         b = 4'd6; 
16         c = a + b; 
17         #100;                      /*100个单位的时间尺度*/
18         $display("%b+%b=%d", a, b, c); 
19     end
20 
21 endmodule

 2、$write 用于输出、打印信息

$write("%b+%b=%d\n",a, b, c); //“%b+%b=%d\n” 格式控制,未指定时默认十进制

% h % H // 以十六进制的形式输出
% d % D // 以十进制的形式输出
% o % O // 以八进制的形式输出
% b % B // 以二进制的形式输出
\n // 换行
1 //a,b,c 为输出列表,需要输出信息的变量
2 `timescale 1ns/1ns 
3 module tb_test(); 
4 
5 reg [3:0] a;
6 reg [3:0] b;
7 reg [3:0] c;
8 
9 initial begin
10     $write("hello ");
11     $write("EmbedFire\n");         /*后面未带有自动换行*/
12     a = 4'd5; 
13     b = 4'd6; 
14     c = a + b; 
15     #100; 
16     $write("%b+%b=%d\n",a, b, c);
17 end
18 
19 endmodule

 3、$strobe 用于输出、打印信息

$strobe("%b+%b=%d",a,b,c); //“%b+%b=%d” 格式控制,未指定时默认十进制

% h % H // 以十六进制的形式输出
% d % D // 以十进制的形式输出
% o % O // 以八进制的形式输出
% b % B // 以二进制的形式输出
1 //a,b,c 输出列表,需要输出信息的变量
2 //打印信息后自动换行,触发操作完成后执行
3 `timescale 1ns/1ns
4 module tb_test ();
5 
6 reg [3:0] a;
7 reg [3:0] b;
8 reg [3:0] c;
9 
10 initial begin
11     $strobe("strobe:%b+%b=%d", a, b, c);
12     a = 4'd5;
13     $display("display:%b+%b=%d", a, b, c);
14     b = 4'd6;
15     c = a + b;
16 end
17 
18 endmodule

4、 $monitor 用于持续监测变量

$monitor("%b+%b=%d",a,b,c); //“%b+%b=%d” 格式控制,未指定时默认十进制

% h % H // 以十六进制的形式输出
% d % D // 以十进制的形式输出
% o % O // 以八进制的形式输出
% b % B // 以二进制的形式输出
1 //a,b,c 输出列表,需要输出信息的变量
2 //被测变量变化触发打印操作,自动换行
3 `timescale 1ns/1ns 
4 module tb_test (); 
5 
6 reg [3:0] a;
7 reg [3:0] b;
8 reg [3:0] c;
9 
10 initial begin
11    a = 4'd5; 
12    #100; 
13    b = 4'd6; 
14    #100; 
15    c = a + b; 
16 end
17 
18 initial $monitor("%b+%b=%d", a, b, c);    /*当变量发生变化是进行打印*/
19 
20 endmodule

 

 5、 $stop 用于暂停仿真,$finish 用于结束仿真

1 `timescale 1ns/1ns 
2 
3 module tb_test(); 
4 
5 initial begin
6     $display("Hello"); 
7     $display("EmbedFire"); 
8     #100; 
9     $display("Stop Simulation"); 
10    $stop; //暂停仿真
11    $display("Continue Simulation"); 
12    #100; 
13    $display("Finish Simulation"); 
14    $finish; //结束仿真
15 end
16 
17 endmodule

6、$time 为时间函数,返回 64 位当前仿真时间;

     $random 用于产生随机函数,返回随机数

1 `timescale 1ns/1ns
2 module tb_test ();
3 
4 reg [3:0] a; 
5 
6 always #10 a = $random;
7 
8 initial $monitor("a=%d @time %d",a,$time); 
9 
10 endmodule

 7、$readmemb 用于读二进制文件函数 ,$readmembh 用于读十六进制文件函数

$readmemb ( "< 数据文件名 >" ,< 存贮器名 >);
$readmemh ( "< 数据文件名 >" ,< 存贮器名 >);
1 `timescale 1ns/1ns
2 module tb_test (); 
3 
4 integer i; 
5 
6 reg [7:0] a [20:0];            /*声明a为位宽为8bit,深度为21的存储器*/
7 
8 initial begin
9     $readmemb("EmbedFire.txt", a); 
10     for(i=0; i<=20; i=i+1) begin
11         #10; 
12         $write("%s", a[i]); 
13     end
14 end
15 
16 endmodule
读取的 txt 文件为
01010111 // W
01100101 // e
01101100 // l
01100011 // c
01101111 // o
01101101 // m
01100101 // e
00100000 // 空格
01110100 // t
01101111 // o
00100000 // 空格
01000101 // E
01101101 // m
01100010 // b
01100101 // e
01100100 // d
01000110 // F
01101001 // i
01110010 // r
01100101 // e
00100001 // !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐者-桥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值