Verilog硬件编程之语法笔记

Admin 2020-04-07 141人围观 ,发现0个评论 Verilog硬件语法笔记

Verilog笔记

Verilog硬件编程之语法笔记 Web教程 第1张

assign:

assign 相当于连线,一般是将一个变量的值不间断地赋值给另一个变量,就像把这两个变量连在一起,所以习惯性的当做连线用,比如把一个模块的输出给另一个模块当输入。

wire型变量赋值,wire 是线网,相当于实际的连接线,如果要用assign直接连接,就用wire型变量。wire型变量的值随时变化。

(1)在Verilog module中的所有过程块(如initial块和always块)、连续赋值语句(如assign语句)和实例引用都是并行的。在同一module中这三者出现的先后顺序没有关系

(2)只有连续赋值语句assign实例引用语句可以独立于过程块而存在于module的功能定义部分。

(3)连续赋值assign语句独立于过程块,所以不能在always过程块中使用assign语句。只有连续赋值语句assign实例引用语句可以独立于过程块而存在于模块的功能定义部分

通过连续赋值语句描述3位加法器module  adder ( count,sum,a,b,cin );input [2:0] a,b;input   cin;output  count;output [2:0] sum;
     assign {count,sum} = a + b + cin;endmodule

通过连续赋值语句描述一个比较器module compare ( equal,a,b );output  equal;    //声明输出信号equalinput [1:0] a,b;  //声明输入信号a,b
 assign  equal =(a = = b)?1:0;/*如果a、b 两个输入信号相等,输出为1。否则为0*/endmodule//版本2module compare_2 ( equal,a,b );output  equal;    //声明输出信号equalinput [1:0] a,b;  //声明输入信号a,breg equal;//

 always @(a,b)
   if(a==b)
     equal=1;
   else
     equal=0;/*如果a、b 两个输入信号相等,输出为1。否则为0*/endmodule//版本3module compare_3 ( equal,a,b );output  equal;    //声明输出信号equalinput [1:0] a,b;  //声明输入信号a,breg equal;//

 always @(a,b)
 begin   //
   if(a==b)
     equal=1;
   else
     equal=0;
 end     //assign  equal =(a = = b)?1:0;/*如果a、b 两个输入信号相等,输出为1。否则为0*/endmodule


always:

always @(a)表示如果a有变化就执行下面的语句

always @(sl or a or b)表示只要slab,其中若有一个变化时就执行下面的语句

Verilog程序包括4个主要部分:

  • 端口定义

  • I/O说明

  • 内部信号声明

  • 功能定义

I/O说明的格式:

  • 输入口 input[范围];

  • 输出口 output [范围];

  • 输入/输出口 inout [范围];

  • I/O说明也可以写在端口声明里。

内部信号说明:

  • reg[范围] 变量1,变量2…;

  • wire[范围] 变量1,变量2…;

模块中实现逻辑功能的3种方法:

(1)assignassign c=a&b;

(2)用实例元件 :and #2 u1(q,a,b);

(3)用always

  • assign语句是描述组合逻辑最常用的方法之一。

  • always块既可用于描述时序逻辑,又可用于组合逻辑。

D触发器:

module new_dff(q,clk,d);
   input clk,d;
   output q;
   reg q;

     always @(posedge clk)
       q<=d;endmodule

D触发器(带异步清除端)

module new_dff2(q,clk,d,clr);input clk,d,clr;output q;reg q;

 always @(posedge clk or  posedge clr)
 begin
   if(clr)
     q<=0;
   else
     q<=d;
 endendmodule

D触发器(带异步清除端和使能端)

module new_dff3(q,clk,d,clr,en);output q;input clk,d,clr,en;reg q;

 always @(posedge clk or  posedge clr)
 begin
   if(clr)
     q<=0;
   else if (en)
     q<=d;
 endendmodule

数据类型及其常量和变量:

4种逻辑值 : 0 1 z(高阻) x (不定值)

常量:在程序运行过程中,其值不能被改变的量称为常量。


整数:

  • 二进制整数 bB

  • 十进制整数 dD

  • 八进制整数 oO

  • 十六进制整数 hH

数字表达方式: <位宽>'<进制><数字>,默认位宽是32bit

4'b1110   //4位二进制数
12'habc  //12位十六进制数16'd255  //16位十进制数

负数: 一个数字可以被定义为负数,只需在位宽表达式前加一个减号,减号必须写在数字定义表达式的最前面。

-8'd5 //这个表达式代表5的补数(用八位二进制数表示)


参数(Parameter)型:

parameter来定义一个标识符 代表一个常量,称为符号常量,即标识符形式的常量,采用标识符代表一个常量可提高程序的可读性和可维护性。是一种常数型的数据,其说明格式如下:

parameter 参数名1=表达式,参数名2=表达式, …, 参数名n=表达式;

parameter是参数型数据的确认符,确认符后跟着一个用逗号分隔开的赋值语句表。在每一个赋值语句的右边必须是一个常数表达式。也就是说,该表达式只能包含数字或先前已定义过的参数。

parameter msb=7; //定义参数msb为常量7parameter e=25, f=29; //定义二个常数参数parameter r=5.7; //声明r为一个实型参数parameter byte_size=8, byte_msb=byte_size-1; //用常数表达式赋值parameter average_delay = (r+f)/2; //用常数表达式赋值

参数型常数经常用于定义延迟时间和变量宽度。在实例引用时可通过参数传递改变在被引用模块中已定义的参数

module two_delay(a,b,c,d);output c,d;input a,b;reg c,d;parameter delay1=2,delay2=2;

 always @(a)
   c<= #delay1 a;

 always @(b)
   d<=#delay2 b;endmodule//调用版本1module top_delay(a1,b1,c1,d1);input a1,b1;output c1,d1;

 two_delay #(.delay1(5),.delay2(10)) u1(.a(a1),.b(b1),.c(c1),.d(d1));endmodule//调用版本2module top_delay2(a1,b1,c1,d1);input a1,b1;output c1,d1;

 two_delay #(5,10) u1(.a(a1),.b(b1),.c(c1),.d(d1));endmodule//调用版本3module top_delay3(a1,b1,c1,d1);input a1,b1;output c1,d1;

 two_delay #(.delay2(10)) u1(.a(a1),.b(b1),.c(c1),.d(d1));endmodule//调用版本4module top_delay4(a1,b1,c1,d1);input a1,b1;output c1,d1;

 two_delay #(10) u1(.a(a1),.b(b1),.c(c1),.d(d1));  //参数被传给了delay1endmodule

变量:

wire变量:wire [n-1:0] 数据名1,数据名2,…数据名i;  //共有i条总线,每条总线内有n条线路wire [n:1] 数据名1,数据名2,…数据名i;wire a;     //定义了一个一位的wire型数据wire [7:0] b;     //定义了一个八位的wire型数据wire [4:1] c, d;     //定义了二个四位的wire型数据///////////////////////////////////////////////////////reg是最常用的寄存器型数据。默认初始值是x:reg [n-1:0] 数据名1,数据名2,… 数据名i;reg [n:1] 数据名1,数据名2,… 数据名i;reg rega; //定义了一个一位的名为rega的reg型数据reg [3:0] regb; //定义了一个四位的名为regb的reg型数据reg [4:1] regc, regd; //定义了两个四位的名为regc和regd的reg型数据

运算符按其功能可分为以下几类:

1) 算术运算符(+,-,×,/,%)
2) 赋值运算符(=,<=)
3) 关系运算符(>,<,>=,<=)
4) 逻辑运算符(&&,||,!)
5) 条件运算符(?:)
6) 位运算符(~,|,^,&,^~)
7) 移位运算符(<<,>>)
8) 拼接运算符({ })
9) 其它

Verilog硬件编程之语法笔记 Web教程 第2张

下面是Verilog HDL中使用的关键词:
always, and, assign,begin,buf,bufif0,bufif1,case,casex,casez,cmos,deassign,default,defparam,disable,edge,else,end,endcase,endmodule,endfunction,endprimitive,endspecify, endtable, endtask, event, for, force, forever, fork, function,highz0,highz1, if,initial, inout, input,integer,join,large,macromodule,medium,module,nand,negedge,nmos,nor,not,notif0,notifl, or, output, parameter, pmos, posedge,primitive, pull0, pull1, pullup, pulldown, rcmos, reg, releses, repeat, mmos, rpmos,rtran, rtranif0,rtranif1,scalared,small,specify,specparam,strength,strong0, strong1,supply0, supply1, table, task, time, tran, tranif0, tranif1, tri, tri0, tri1, triand,trior, trireg,vectored,wait,wand,weak0,weak1,while, wire,wor, xnor, xor

块语句:

begin_end语句 通常用来标识顺序执行的语句,用它来标识的块称为顺序块

顺序块有以下特点:

(1) 块内的语句是按顺序执行的,即只有上面一条语句执行后下面的语句才能执行。(2) 每条语句的延迟时间是相对于前一条语句的仿真时间而言的。(3) 直到最后一条语句执行完,程序流程控制才跳出该语句块。

块内声明语句可以是参数声明语句、reg型变量声明语句、integer型变量声明语句、real型变量声明语句。

module ex4_5;parameter d=50;reg[7:0] r;reg[3:0] a;event end_wave;

 always @(end_wave)
   a=4'hf;
   initial
      begin
        a=4'h2;
      end

   initial      begin
       #d r='h35;
       #d r='hE2;
       #d r='h00;
       #d r='hF7;
       #d ->end_wave;
     endendmodule

逻辑判断:

module counter10b(q,clk,clr);output[3:0] q;input clk,clr;reg[3:0] q=4'b0000;//ModelSim仿真用,QuartusII不用初值
 always @(posedge clk or posedge clr)
 begin
   if(clr)
     q<=4'b0000;
   else
   begin
     if (q==4'b1001)
       q<=4'b0000;
     else
       q<=q+1'b1;
   end
 end
endmodule

case语句:

case语句是一种多分支选择语句,if语句只有两个分支可供选择,而实际问题中常常需要用到多分支选择,Verilog语言提供的case语句直接处理多分支选择。

case语句的所有表达式的值的位宽必须相等,只有这样控制表达式和分支表达式才能进行对应位的比较。一个经常犯的错误是用’bx, ‘bz 来替代 n’bx, n’bz,这样写是不对的,因为信号x, z的缺省宽度是机器的字节宽度,通常是32位(此处 n 是case控制表达式的位宽)

module test_case;reg[1:0] select;
 initial  begin
   select=2'b01;
   case (select)
     2'b01:$display("second 2b01...");
     2'b01:$display("third 2b01...");
     2'b01,2'b00:$display("2b01");
     2'b11:$display("2b11");
     default:$display("default...");
   endcase  endendmodule

initial 和 always 说明语句在仿真的一开始即开始执行。

initial 语句只执行一次。相反,always 语句则是不断地重复执行,直到仿真过程结束。

always 语句后面跟着的过程块是否运行,则要看它的触发条件是否满足,如满足则运行过程块一次,再次满足再运行一次,直至仿真过程结束。

在一个模块中,使用initial 和 always 语句的次数是不受限制的。

task 和function 语句可以在程序模块中的一处或多处调用。

@* 和 @(*),它们都表示对其后面语句块中所有输入变量的变化时敏感的。


请发表您的评论
请关注微信公众号
微信二维码
不容错过
Powered By 蚁人博客