Verilog HDL笔记

模块

模块介绍

  • 模块是Verilog HDL语言的基本单元,数字系统是用模块的形式来描述。
  • 模块是描述某个设计的功能、结构和其他模块通信的外部端口。
  • Verilog HDL中的各个模块是并行运行的
  • 模块可以调用其他模块的实例

模块结构

module <模块名>(<端口列表>)
    端口说明(input,output,inout)
    参数定义(可选)
    数据类型定义//wire、reg、task、function
    连续赋值语句(assign)//组合逻辑
    过程块(always和initial)
    -行为描述语句
    低层模块实例//调用其它模块
    任务和函数
    延时说明块
endmodule

语句模块描述方式

Verilog有三种建模方式,分别是

  • 结构化描述方式
  • 数据流描述方式
  • 行为描述方式

结构型描述

通过实例进行描述的方法,将预定义的基本原件实例嵌入语言中,监控实例的输入,一单任何一个发生变化便重新运算并输出。

数据流型描述

是一种描述组合逻辑功能的方法,用assign连续赋值语句来实现。

连续赋值语句完成如下的组合功能:等式右边的所有变量受持续监控,每当这些变量中有任何一个发生变化,整个表达式被重新赋值并送给等式左端。

行为级描述

是通过描述行为特性来实现,关键词是always,含义是一单敏感变量发货时能变化,就重新一次进行赋值,有无限循环之意。这种描述方法常用来实现时序电路,也可用来描述组合功能。

Tip

用户可以混用上述三种描述方法,但需要说明的是,模块中门的实例、模块实例语句、assign语句和always语句是并发执行的,即执行顺序和书写次序无关。

  • Verilog HDL区分大小写
  • Verilog HDL关键字一般为小写

其中数据流描述方式经常使用连续赋值语句,某个值被赋给某个网线变量。

assign [delay] net_name = expression;

注意在各assign 语句之间,是并行执行的,即各语句的执行与语句之间的顺序无关。

行为描述方式经常使用always、initial语句赋值。使用reg进行寄存器的声明。always是指一直在重复运行,由always后面括号的变量变化时触发。在always以及end之间是串行顺序执行的。

数据流型描述是一种描述组合逻辑功能的方法,用assign连续赋值语句来实现。

常量

数字

语法:

<位宽>‘<进制><数值>

其中位宽是指对应二进制的位数

需要注意的是,尾款小于相应数值的实际位数时,相应的高位部分被忽略。4‘D614‘B1101相同。因为十进制下61==111101,这里要求二进制4bit,所以是1101.

parameter

语法:

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

例:

parameter count_bits=8;
parameter sel=8,code=8‘ha3;
parameter datawidth=8;addwidth=datawidth*2;

使用常量的目的:

  • 便于阅读
  • 便于修改

变量

  • 网络型 nets type

指硬件电路中的各种连接,输出始终根据输入的变化更新其值的变化。

  • 寄存器型 register type

常指硬件中电路中具有状态保持作用的器件,如触发器、寄存器等等。



nets type中最主要的就是wire型变量,常用来表示用assign语句赋值的组合逻辑信号。可以取值为0,1,x(不定值),z(高阻)

注意,Verilog HDL模块中的输入输出信号类型缺省时,自动定义为wire型变量。

语法:

wire 数据1,数据2,……数据n.

例子:

wire a,b,c //定义了三个wire型变量

wire[7:0] databus //定义了8bit宽wire型向量数据总线

wire[20:1] addrbus  //定义了20bit宽的wire型向量地址总线


这里记录下register type中的reg型,常用的寄存器型变量

语法: reg 数据1,数据2,数据3……;

例子:

reg a,b;

reg[8:1] data //定义可8bit宽的reg型向量

reg[7:0] mymem[1023:0] //定义了1024字节(8bit*1024)的存储器

常用语句

  • 赋值 连续赋值语句、过程赋值语句
  • 条件语句 if-else语句、case语句
  • 循环语句 forever、repeat、while、for语句
  • 结构说明语句 initial、always、task、function语句
  • 编译预处理语句 ‘define ‘include ‘timescale语句

过程块

  1. always过程块

模板:

always @(<敏感信号表达式>)
begin
    //过程赋值
    //if语句
    //case语句
    //while、repeat、for语句
    //task、function调用
end

当敏感信号表达式的值改变时候,就执行一遍块内语句。同时always过程块是不能够嵌套使用的。

关键字posedgenegedge关键字分别是上升沿以及下降沿

例如:同步时序电路的时钟信号为clk,clear为异步清零信号。敏感信号可写为:

//上升沿触发,高电平清0有效
always @(posedge clk or posedge clear)

//上升沿触发,低电平清0有效
always @(posedge clk or negedge clear)

例如当negedge clear表示当clear==0

always @(posedge clk or negedge clear)
    begin
        if(!clear)//当clear==0时候,always会由事件驱动
            qout=0;
        else
            qout=in;
    end
  1. initial过程块

initial模板:

initial
begin
    语句1;
    语句2;
    ......
end

对变量和存贮器初始化

initial
begin
    reg1=0;
    for(addr=0;addr<size;addr=addr+1)
        memory[addr]=0;
end
  • initial语句主要面向功能模拟,通常不具有可综合性。
  • 模拟0时刻开始执行,只执行一次
  • 同一模块内的多个initial过程块,模拟0时刻开始并行执行。

initial与always语句一样,是不能嵌套使用的。即在initial语句中不能再次嵌套initial语句块。

赋值语句

  1. 连续赋值语句assign常用于对wire型变量进行赋值
input a,b;
output c;
assign c=a&b;

a,b信号的任何变化,都将随时反映到c上来。

  1. 过程赋值语句常用于对reg型变量进行赋值

一般分为两种方式:

  • 非阻塞赋值:一条非阻塞赋值语句的执行是不会阻塞下一条语句的执行,也就是收本条非阻塞赋值语句的执行完毕之前,下一条语句也可以开始执行。非阻塞赋值语句在块结束时才一同完成赋值操作,在一块内非阻塞赋值语句并行执行。赋值符号<=
  • 阻塞赋值:该语句结束时就完成赋值操作,前面的语句没有完成之前,后面的语句是不能执行的,在一块内非阻塞赋值语句顺序执行。赋值符号=

非阻塞赋值:

module non_block (c, a,b,clk);
output c,b;
input a,clk;
reg c,b;
always @(posedge clk)
    begin
        b<=a;
        c<=b;
    end
endmodule

由于是非阻塞赋值,bc在clk上升沿同时进行状态变化。所以b<=a;c<=b;语句在同时执行,所以c的值是b上一个上升沿的值,b的值被赋值为a上一个上升沿的值。

阻塞赋值:

module block (c, a,b,clk);
output c,b;
input a,clk;
reg c,b;
always @(posedge clk)
    begin
        b=a;
        c=b;
    end
endmodule

顺序执行有c==b

条件语句

if-else语句块

pass

case语句

case (<敏感表达式>)
    值1:语句或语句块1 ;//case分支项
    值2:语句或语句块2 ;
    ……
    值n:语句或语句块n ;
    default:语句或语句块n+1;//可省略
endcase

Tips

  • 若没有列出所有条件分支,编译器认为条件不满足时,会引进触发器保持原值。
  • 时序电路可利用上述特性来保持状态。
  • 组合电路必须列出所有条件分支,否则会产生隐含触发器。

8bit二进制乘法器 integer

module mult_for (outcome,a,b);
parameter size=8 ;
output[2*size:1] outcome;
input[size:1] a,b; //乘数
reg[2*size:1] outcome; //积
integer i;
always @(a or b)
    begin
        outcome=0;
        for (i=1;i<=size;i=i+1)
        if(b[i]) outcome=outcome+( a<<(i-1) ) ;
    end
endmodule

task、function

task

定义格式:

task<任务名>
    端口与类型说明
    局部变量说明
    语句或语句块
endtask

调用格式:

<任务名>(port1,port2,port3,......)

函数function

定义格式:

function <返回值位宽或类型> <函数名>
    输入端口与类型说明
    局部变量说明
    语句或语句块
endfunction

调用格式:

<函数名> (<输入表达式1>,<输入表达式2>,<输入表达式3>,......)

module function_example(i,out);
input[7:0] in;
output[2:0] out;
reg[2:0] out;
    function[2:0] gefun;
        input[7:0] x; //输入端口说明
        reg[2:0] count;
        integer i;
        begin
            count=0;
            for(i=0;i<=7;i=i+1)
                if(x[i]==1‘b0)count=count+1;
            gefun=count;
        end
    endfunction
    always @(in) out=gefun(in);//这里要注意的是 in要与x位宽相同
endmodule

Verilog中函数function声明,在声明的最后一句一般都是对结果赋值。也就是对函数名赋值。如上例中,函数名gefun,在声明最后一句就是对gefun的赋值。

编译预处理

  • `define
  • `include
  • `timescale

编译指令以”`”反引号开头。不同于整数的单引号,预编译使用的是反引号,一般在键盘的左上角。

顺序与并行

  • assign语句之间:并行执行(同时执行)
  • 过程块之间(always、initial):并行执行
  • assign语句与过程块之间:并行执行
  • 过程块(initial、always)内部
    1. 串行块(begin-end):顺序执行—非阻塞语句类似于并行语句
    2. 并行快(fork-join):并行执行
时间: 2024-10-12 23:20:27

Verilog HDL笔记的相关文章

verilog HDL学习笔记(基本概念)

1. 作为一种硬件描述语言,verilog可以直接描述硬件结构,也可以通过描述系统行为实现建模,其主要特点和功能有: *描述基本逻辑门和基本开关模型. * 允许用户定义基元. * 可以指定设计中的端口到端口的延时,路径时延和设计中的时序检查. *可以采用多种方式进行建模,这些方式包括(1)顺序行为描述建模——使用过程化结构建模,(2)数据流行为方式——使用连续赋值语句方式建模,(3)结构化方式——使用门和模块实例语句描述建模. * Verilog中有两类数据类型,线网数据类型和寄存器数据类型.线

【黑金教程笔记之003】【建模篇】akuei2的Verilog hdl心路

Verilog hdl不是“编程”是“建模” Verilog hdl语言是一种富有“形状”的语言. 如果着手以“建模”去理解Verilog hdl语言,以“形状”去完成Verilog hdl语言的设计.在感觉上Verilog hdl + FPGA是“可所触及”,是一种“实实在在”的感觉,不相等于“编程”时的那种“抽象感”. “低级建模”最基本最简单之意,建模习惯or风格.

MiS603开发板 2.1 Verilog HDL 代码规范

作者:MiS603开发团队 日期:20150911 公司:南京米联电子科技有限公司 论坛:www.osrc.cn 网址:www.milinker.com 网店:http://osrc.taobao.com EAT博客:http://blog.chinaaet.com/whilebreak 博客园:http://www.cnblogs.com/milinker/ 2.1 Verilog HDL 代码规范 规范的代码风格,可以让程序更容易阅读和维护. u 文档管理 合理的文档管理也是程序代码规范的重

verilog 建模笔记--低级建模

来源  <verilog HDL那些事--建模篇> 1.并行建模的思想. 2.每个模块最好只有一个功能.(便于修改和扩展,特别在大的项目中) 典型的 HDL 教科书中,才不会要读者了解“模块的性质”.没有性质的模块,常常会使得初学着在设计上和理解容易陷入“混乱”.反之,如果“模块含有性质”的话,在设计和理解方面,思路会而外的清晰.笔者尝试使用“低级建模”去完成程式设计,感觉都是得心应手,而且设计越发的清晰.虽然“低级建模”的建模量确实很多,但是可以把它看成是一种修行练功. verilog HD

浅谈Verilog HDL代码编写风格

消失了好久,没有写文章,也没有做笔记,因为最近再赶一个比赛,时间很紧,昨天周六终于结束了,所以趁着周末这会儿有时间,写点东西,记录下来.首先我学习FPGA才一年多,我知道自己没有资格谈论一些比较深层次的问题,对于这个行业来说可能我才是一直脚踩在门外面.所以这篇文章是写给一些刚开始学习FPGA.Verilog HDL的同学,我看过一些大神写的代码,然后尽量模仿大神写法,经过好几个大神的影响和自己的习惯摸索,最终算是总结出了一套自己的代码书写风格,当然我的代码风格还是一直在进化中.现在将自己的一些经

3_8译码器Verilog HDL语言的简单实现

最近在学Verilog HDL语言,觉得learn in doing是比较好的学习方式,所以我们来直接分析分析代码好了. 先来一波代码: 1 module q_decode_38(data_in,data_out); 2 3 input[2:0] data_in; //端口声明 4 output[7:0] data_out; 5 reg[7:0] data_out; 6 7 always@(data_in) 8 begin 9 case(data_in) 10 3'd0:data_out = 8

基于Verilog HDL整数乘法器设计与仿真验证

基于Verilog HDL整数乘法器设计与仿真验证 1.预备知识 整数分为短整数,中整数,长整数,本文只涉及到短整数.短整数:占用一个字节空间,8位,其中最高位为符号位(最高位为1表示为负数,最高位为0表示为正数),取值范围为-127~127. 负数的表示方法为正值的求反又加1.例如: 8’b0000_0100; //表示值:4,正值求反为:8’b1111_1011:再加1表示为:8’b1111_1100,这样便得到了-4的表示方法为:8’b1111_1100. 同理,负值变成正值的方法为:负值

&lt;转&gt;Verilog HDL宏定义define

宏定义 `define 用一个指定的标识符(即名字)来代表一个字符串,它的一般形式为: `define 标识符(宏名) 字符串(宏内容) 如:`define signal string 它的作用是指定用标识符signal来代替string这个字符串,在编译预处理时,把程序中在该命令以后所有的signal都替换成string.这种方法使用户能以一个简单的名字代替一个长的字符串,也可以用一个有含义的名字来代替没有含义的数字和符号,因此把这个标识符(名字)称为“宏名”,在编译预处理时将宏名替换成字符串

自己动手写处理器之第二阶段(3)——Verilog HDL行为语句

将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第七篇,我尽量每周四篇 2.6 Verilog HDL行为语句 2.6.1 过程语句 Verilog定义的模块一般包括有过程语句,过程语句有两种:initial.always.其中initial常用于仿真中的初始化,其中的语句只执行一次,而always中语句则是不断重复执行的.此外,always过程语句是可综合的,initial过程语句是不可综合的.       1.always过程语句 always过程语句的格式如图2-10所示.