当前位置:   article > 正文

verilog study-初级_very log中注释

very log中注释

目录

简介

语言要素和数据类型

语言要素

数据类型

运算符和表达式

优先级:

算术运算符:    

关系运算符

相等关系运算符

规约运算符:

移位运算符:

条件运算符:

连接和复制运算符:

模块 module:

端口:

程序设计语句

数据流建模

行为级建模

        可综合描述语句:

        initial过程语句

        always过程语句

        语句块 

        过程赋值语句: 

        过程连续赋值语句

        条件分支语句

        循环语句

结构化建模

模块级建模

        模块调用方式:

        模块端口对应方式:

        模块参数值

门级建模

开关级建模

组合电路设计

3个裁判的表决电路

case语句

逻辑代数方式

结构描述方式

抽象描述方式

数字加法器

真值表

代数逻辑表示为

4位超前进位加法器

数据比较器

数据选择器

数字编码器

8线-3线优先编码器

二进制转化十进制8421BCD编码器

8421BCD十进制余3码编码器

数字译码器

2线-4线译码器

奇偶校验器

时序电路设计

 状态图描述

化简描述 

 抽象描述方式

触发器

最简D触发器

带复位端的D触发器 

复杂功能的D触发器 

T触发器

计数器

二进制计数器

任意进制计数器 

移位寄存器

环形移位寄存器

序列信号发生器

由移位寄存器构成

由移位寄存器和组合逻辑电路构成 

由计数器构成

有限同步状态机

状态机的编码方式:

状态机的两段式描述方法:

状态机的三段式描述方法:

4位顺序脉冲发生器

 自动售报机

“11010”序列检测器

电路仿真和测试程序

语言要素

 $display $write

 $monitor 和 $strobe

$time 和 $realtime

$readmemh 和$readmemb

$random

VCD

十进制加法器


简介

本文将涉及verilog的设计方法,探索使用verilog hdl描述数字电路,探索verilog的语言特性。

内容总结于诚聘英才 > 在线课堂_西安电子科技大学微电子学院

【电子】Verilog硬件描述语言 西安电子科技大学 蔡觉平等主讲_哔哩哔哩_bilibili

语言要素和数据类型

语言要素

空白符:空格符(\b),制表符(\t),换行符,换页符
注释符:
        单行注释: 单行注释以 “// 开始
        多行注释 多行注释以 /* 开始 */ 结束
标识符和转义标识符:
        标识符:字母、 数字 $ 符号和 _ 下划线 符号
        转义标识符:“ \ 反斜线 符号开头 以空白结尾 空白可以是一个空格 一个制表字符或换行符
关键字:用来组织语言结构。
数值:
        四值电平逻辑:
        
状态
含义
0
低电平 逻辑 0 或''假
1
高电平 逻辑 1
x X
不确定或未知的逻辑状态
z Z
高阻态

        整数:+/-<size>'<base_format>number>

数制
基数符号
数字字符集
二进制
b B
0 1 X X z Z ? _
八进制
o 或O
0~7 X X z Z ? _
十进制
d D
0 9 _
十六进制
h H
0~9 a f A F X X z Z^ ? _

                注意事项:

  • 在较长的数之间可以用下划线来分开
  • 当数字没有说明位宽时 默认为 32
  • x z 在二进制中代表 1 x z, 在八进制中代表 3 x z, 在十六进制中代表4位 x z
  • 若没有定义一个整数的位宽,其宽度为相应值中定义的位数。
  • 若定义的位宽比实际数的位数大 则在左边用 0 补齐 但如果数最左边一位为 x 或z,就相应地用 x z 在左边补齐。如果定义的位宽比实际数的位宽小 那么最左边的位被截断。
  • “?”是高阻态z的另一种表示符号。在数字的表示中,字符"?”和z或Z是等价的,可互相替代。
  • 整数可以带正 负号 并且正 负号应写在最左边 负数表示为二进制的补码形式。-4 等价于 4'b1100
  • 如果位宽和进制都缺省 则代表十进制数
  • 数字中不能有空格 但在表示进制的字母两侧可以有空格
实数:
        十进制表示法:小数点两边必须都有数字
        科学计数法:564.2e2
的值为 56420.0。
字符串:字符串是指用双引号括起来的字符序列。  

数据类型

数据类型共有 19 种:
        wire、 tri tri0 tri1 wand triand 、trireg、 trior 、  wor、  reg large small scalared、  medium 、  vectored integer time real、 parameter
物理数据类型:
         强度等级:
标记符
名称
类型
强弱程度
supply
电源级驱动
驱动
1
strong
强驱动
驱动
2
pull
上拉级驱动
驱动
3
large
大容性
存储
4
weak
弱驱动
驱动
5
medium
中性驱动
存储
6
small
小容性
存储
7
highz
高容性
高阻
8

        连线型:<net_declaration> <drive_strength><rangexdelay>[list_of_variables];

连线型数据类型
功能说明
wire, tri
标准连线型 缺省为该类型
wor, trior
多重驱动时 具有线或特性的连线型
wand, trand
多重驱动时 具有线与特性的连线型
trireg
具有电荷保持特性的连线型 特例
tri1
上拉电阻
tri0
下拉电阻
supply1
电源线 用于对电源建模 为高电平1
suppIy0
电源线 用于对 建模 为低电平 0

                wire 和 tri :

                        wire型变量通常用来表示单个门驱动或连续赋值语句驱动的连线型数据。

                        tri型变量则用来表示多驱动器驱动的连线型数据,主要用于定义三态的线网

wire/tri
0
1
xz
0
0xx0
1
x1x1
xxxxx
z01xz

        寄存器型:reg型:数据储存单元的抽象类型,能够存储数据如触发器、锁存器等,

                reg型变量:常用于行为级描述中,由过程赋值语句对其进行赋值

                格式:reg<range><list_of_register_variables>;

        存储器型:存储器型(memory)本质上还是寄存器型变量阵列,存储器型变量可以描述RAMROM型存储器以及reg文件。

                用reg型变量建立寄存器组(数组)来实现存储器的功能

                格式:reg<range 1><name_of_regisler><range2>;

抽象数据类型:

        整型:integer<list_of_register_variables>;

                整型数据常用于对循环控制变量的说明,在算术运算中被视为二进制补码形式的有符

号数。

        时间型:lime<list_of_register_variables>;

                时间型数据与整型数据类似只是它是64位的无符号数。

        实型:real<list_of_variables>;

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

  •                 表达式既可以是常数,也可以是表达式参数定义完以后程序中出现的所有的参
数名都将被替换为相对应的表达式
  •                 另外,对于同一个模块来说参数一旦被定义就不能够通过其它语句对它重新赋值

运算符和表达式

优先级:

运算符
优先级别
!、~
反逻辑 位反相
1
* /
取模
2
+ -
3
<<、>>
左移 右移
4
<= >=
小于 小于等于 大于 大于等于
5
==、!=、===、!==
不等 全等 非全等
6
&
按位与
7
^ ^ ~
按位逻辑异或和同或
8
I
按位逻辑或
9
&&
逻辑与
10
II
逻辑或
11
?:
条件运算符 唯一的三目运算符 等同于 if-else
12

算术运算符    

                注意事项:

  • 算术运算结果的位宽:算术表达式结果的长度由最长的操作数决定。
  • 有符号数和无符号数的使用:
    • 无符号数值一般存储在线网、reg(寄存器)型变量及普通(没有符号标记s)的基数格式表示的整型数中。
    • 有符号数值一般存储在整型变量、十进制形式的整数、有符号的reg(寄存器)型变量及
      有符号的线网中

关系运算符

相等关系运算符

        ==:
==01xz
010xx
101xx
xxxxx
zxxxx

        ===:

===01xz
01000
10100
x0010
z0001

        逻辑运算符:

ab!a!ba&&ba||b
110011
100101
011001
001100

        按位运算符:

                &:

&01x
0000
101x
x0xx

                |:

|01x
001x
1111
xx1x

                ^:

^01x
001x
110x
xxxx

                        两个不同长度的数据进行位运算时,会自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐然后逐位进行运算,运算结果的位宽与操作数中位宽较大者相同

规约运算符:

         缩位运算符包括&(与I ^异或以及相应的非操作~&~|、~^、^~。

         归约运算符的操作数只有一个。

移位运算符:

          左移位运算符(<<)右移位运算符(>>)

条件运算符:

          <条件表达式>?<表达式1>:<表达式2>

          条件表达式的运算结果有真(1)(0)和不定态(x)三种当条件表达式的结果为真时

执行表达式 1 当条件表达式的结果为假时 执行表达式 2

                 

           如果条件表达式的运算结果为不定态x,则模拟器将按位对表达式1的值与表达式2的值

进行比较 位与位的比较按表 的规则产生每个结果位 从而构成条件表达式的结果值
?:01xz
00xxx
1x1xx
xxxxx
zxxxx

连接和复制运算符:

                连接运算符 {} :{信号1的某几位信号2的某几位信号n的某几位}。

                复制运算符 {{}} :将一个表达式放入双重花括号中复制因子放在第一层括号中。

模块 module:

端口:

                声明方式:               

                        输入端口: input[倩号位宽-1:0]端口名1

                        输出端口: output[信号位宽-1:0]端口名1

                        输入瀚出端口: inout[信号位宽-1:0]端口名1;

               模块引用时端口的对应方式:

                        模块名(连接端口 1信号名,连接端口 2信号名);

                        模块名 .端口 1 连接信号 1 .端口 2 连接信号 2
                

程序设计语句

数据流建模

        显式连续赋值语句:
                <net_declaration><range><name>;
                assign #<delayxname> = Assignment expression;
        隐式连续赋值语句:
                <net_declaiation><drive_strength><range>#<delay><name> = assignment expression
                ps. wire(strong0, weak1)[3:0]#(2, 1, 3) w = (a^b)&(m^n);        //对于变量w:赋“0”值时的驱动强度较强,为strong:赋“1”值时的驱动强度较弱,为weak。比如,当0和1共同驱动变量w时,由于0定义的驱动强度较强,所以w为0。
        注意事项:
  • 赋值目标只能是线网类型(wire)
  • 在连续赋值中 只要赋值语句右边表达式任何一个变量有变化 表达式立即被计算 , 计算的结果立即赋给左边信号(若没有定义延时量)。
  • 连续赋值语句不能出现在过程块
  • 多个连续赋值语句之间是并行关系 因此与位置顺序无关
  • 连续赋值语句中的延时具有硬件电路中惯性延时的特性 任何小于其延时量的信号变化脉冲都将被滤除掉, 不会出现在输出端口

行为级建模

        可综合描述语句:

                过程语句 always

                语句块 串行语句块begin-end 

                赋值语句 过程赋值语句=、<=

                条件语句 if-else case, casez, casex

                循环语句 for

                编译向导语句 'define 'include 'ifdef, 'else, 'endif

        不可综合描述语句:

                过程语句 initial

                语句块 并行语句块fork-join  

                赋值语句 过程连续赋值语句assign

                循环语句 forever repeat while

                编译向导语句 'define 'include 'ifdef, 'else, 'endif

        initial过程语句

                initial过程语句通常用于仿真模块中对激励向量的描述或用于给寄存器变量赋初值

                initial过程块在进行仿真时从模拟0时刻开始执行它在仿真过程中只执行一次在执

行完一次后该 initial 过程块就被挂起 不再执行
  1. initial
  2. begin
  3. 语句I;
  4. 语句2;
  5. 语句n;
  6. end
  1. module initial_tb1:
  2. reg A, B, C;
  3. initial
  4. begin
  5. A = 0;B= 1;C = O;
  6. #100 A= 1; B = 0;
  7. #100 A = 0;C= I;
  8. #100 B = 1;
  9. #100 B = 0; C = 0;
  10. end
  11. endmodule

        always过程语句

  1. always@(<敏感事件列表>)
  2. 语句块;
  3. @(a) //当信号a的值发生改变时
  4. @(a or b) //当信号a或信号b的值发生改变时
  5. @(posedge clock) //当clock的上升沿到来时
  6. @(negedge clock) //当clock的下降沿到来时
  7. @(posedge elk or negedge reset) //当clk的上升沿到来或reset信号的下降沿(低电平有效)到来时

                注意事项:

  • 在信号的形式定义方面 无论是对时序逻辑电路还是对组合逻辑电路进行描述 Verilog HDL要求在过程语句 initial always 被赋值信号必须定义为 reg 类型
  • 敏感事件列表:
    • 采用过程语句对组合电路进行描述时 需要把全部的输入信号列入敏感事件列表
    • 采用过程语句对时序电路进行描述时 需要把时间信号和部分输入信号列入敏感事件列表

        四选一数据选择器

  1. /*四选一数据选择器*/
  2. module mux4_l(out, in0, in1, in2, in3, sel):
  3. output out;
  4. input in0, ini, in2, in3;
  5. inpul[1 :0] sel;
  6. reg out; 〃被赋值信号定义为“reg”类型
  7. always @(in0 or ini or in2 or in3 or sel) 〃敏感事件列表
  8. case(sel)
  9. 2'b00: out = inO;
  10. 2'b01: out = ini;
  11. 2'b10: out = in2;
  12. Z'b11: out = in3;
  13. default: out = 2'bx;
  14. endcase
  15. endmodule

        同步置数同步清零计数器:

  1. module counter 1 (out, data, load, rst, elk);
  2. output[7:0] out;
  3. input[7:0] data;
  4. input load, elk, rst;
  5. reg[7:0] out;
  6. always @(posedge elk) //clk上升沿触发
  7. begin
  8. if(!rst) out = 8'h00; //同步清零,低电平有效
  9. else if(load) out = data; //同步置数
  10. else out = out+ 1;
  11. end
  12. endmodule

        异步清零计数器:

  1. module counter2(rst, elk, out);
  2. output[7:0] out;
  3. input elk, rst;
  4. reg[7:0] out;
  5. always @(posedge clk or negedge rst) // clk 上升沿和 rst 低电平清零有效
  6. begin
  7. if(!rst) //异步清零
  8. out = 0;
  9. else out = out+1;
  10. end
  11. endmodule

        语句块 

                串行语句块:其中的语句按串行方式顺序执行,可以用于可综合电路程序和仿真测试程序

                        块名即该块的名字,当块内有变量时必须有块名,否则在编译时将出现语法错误。块内声明语句是可选的,可以是参数说明语句integer型变量声明语句reg型变量声明语句、time型变量声明语句和事件(event)说明语句

  1. begin:块名
  2. 块内声明语句;
  3. 语句1;
  4. 语句2;
  5. ...
  6. 语句n;
  7. end

                 并行语句块:语句按并行方式执行,只能用于仿真测试程序,不能用于可综合电路程序。

  1. fork:块名
  2. 块内声明语句:
  3. 语句1;
  4. 语句2;
  5. ...
  6. 语句n;
  7. join

                 两者比较:

语句块
串行语句块 (begin-cnd)
并行语句块 (fork-join)
执行顺序
按照语句顺序执行
所有语句均在同一时刻执行
语句前面延迟
时间的意义
相对于前一条语句执行结束的相对时间
相对于并行语句块启动的时间
起始时间
首句开始执行的时间
转入并行语句块的时间
结束时间
最后一条语句执行结束的时间
执行时间最长的那条语句执行 结束的时间
行为描述的 意义
电路中的数据在时钟及控制信号的作用下 , 沿数据通道中各级寄存器之间传送的过程
电路上电后 各电路模块同时开始工作的过程

        过程赋值语句: 

                阻塞赋值语句:变量=表达式

                                当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成则后面的语句就不能被执行,仿佛被阻塞了一样因此称为阻塞赋值方式

                        特点:

                                在串行语句块中,各条阻塞赋值语句将按照排列顺序依次执行在并行语句块中的各条阻塞赋值语句则同时执行,没有先后之分

                                执行阻塞赋值语句的顺序是,先计算等号右端表达式的值然后立刻将计算的值赋给左边的变量,与仿真时间无关

                非阻塞赋值语句 变量 <=表达式

                        特点:

                               在串行语句块中,各条非阻塞赋值语句的执行没有先后之分排在前面的语句不会影响到后面语句的执行各条语句并行执行

                                执行非阻塞赋值语句的顺序是,先计算右端表达式的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。

        过程连续赋值语句

                赋值语句和重新赋值语句:assign deassign:使用assign给寄存器型变量赋值之后该值将一直保 持在这个寄存器上,直至遇到deassign。

                        assign <寄存器型变量>=<赋值表达式>

                        deassign<寄存器型变量>

                强制语句和释放语句:force release:主要用于Verilog HDL仿真测试程序中便于对某种信号进行临时性的赋值和测试。

                        force <寄存器或连线型变量>=<赋值表达式>;

                        release<寄存器或连线型变量>;

        条件分支语句

                if语句:

  1. if(条件表达式)语句块; //form 1
  2. if(条件表达式) //form 2
  3. 语句块1;
  4. else
  5. 语句块2;
  6. if(条件表达式1) //form 3
  7. 语句块1;
  8. else if(条件表达式2)
  9. 语句块2;
  10. ...
  11. else if(条件表达式i)
  12. 语句块i;
  13. else
  14. 语句块n;

        case语句: 

  1. case(控制表达式)
  2. 1:语句块1
  3. 2:语句块2
  4. ...
  5. 值n:语句块n
  6. default:语句块 n+l
  7. endcase

                case语句的真值表:

case01xz
01000
10100
x0010
z0001

                 BCD数码管译码:

  1. module BCD_decoder(out, in);
  2. output[6:0]out;
  3. input[3:0]in;
  4. reg[6:0]out;
  5. always@(in)
  6. begin
  7. case(in)
  8. 4'b0000:out = 7'b1111110;
  9. 4'b0001:out = 7'b0110000;
  10. 4'b0010:out = 7'b1101101;
  11. 4'b0011:out = 7'b1111001;
  12. 4'b0100:out = 7'b0110011;
  13. 4'b0101:out = 7'b1011011;
  14. 4'b0110:out = 7'b1011111;
  15. 4'b0111:out = 7'b1110000;
  16. 4'bl000:out = 7'blllllll;
  17. 4'bl001:out = 7'bllll011;
  18. default:out = 7'bx;
  19. endcase
  20. end
  21. endmodule

                 casez:比较双方有一位为z,即认为这一位永远为真

casez01xz
01001
10101
x0011
z1111

                casex:比较双方有一位为x或z,即认为这一位永远为真

casex01xz
01011
10111
x1111
z1111

        循环语句

                forever 语句

forever 语句或语句块;
  1. module forever_tb;
  2. reg clock;
  3. initial
  4. begin
  5. clock = 0;
  6. forever #50clock = ~clock;
  7. end
  8. endmodule

                repeat 语句

  1. repeat(循环次数表达式)
  2. 语句或语句块(循环体)
  1. module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。
  2. reg clock;
  3. inilial
  4. begin
  5. clock = 0;
  6. repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号
  7. end
  8. endmodule

                 while 语句

while(条件表达式)语句或语句块;
  1. module while_tb;
  2. reg clock;
  3. initial
  4. begin
  5. clock = 0;
  6. while(l)
  7. #50 clock = ~clock;
  8. end
  9. endmodule

                 for语句

for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
  1. module for_clk;
  2. reg cik;
  3. integer i;
  4. initial
  5. begin
  6. elk = 0;
  7. for(i = 0; i >= 0: i = i+1)
  8. #50 elk = ~clk;
  9. end
  10. endmodule

                        8位移位寄存器

  1. //采用赋值语句实现
  2. module shift_registl(Q, D, rst, elk);
  3. output [7:0] Q;
  4. input D, rst, elk:
  5. reg [7:0] Q;
  6. always @(posedge elk)
  7. if(!rst) Q <= 8'b000000;
  8. else Q <= {Q[6:0], D};
  9. endmodule
  10. //采用for语句实现
  11. module shift_regist2(Q, D, rst, elk);
  12. output [7:0] Q;
  13. input D, rst, elk;
  14. reg [7:0] Q;
  15. integer i;
  16. always @(posedge elk)
  17. if(!rst)Q<= 8'b000000;
  18. else
  19. begin
  20. for (i = 7; i > 0; i = i-1) Q[i] <= Q[i-1];
  21. Q[0] <= D;
  22. end
  23. endmodule

结构化建模

模块级建模

        模块调用方式:

                模块名参数值列表实例名(端口名列表)

        模块端口对应方式:

                端口位置对应方式

                        模块名〈参数值列表实例名(<信号名1>. <信号名2>, ,<信号名n>)

                端口名对应方式

                        模块名〈参数值列表实例名(.端口名1<信号名1>, .端口名2<信号名2>, .端口名n<信号名 n>)

                        dff U4(.q(), ,d(out[2]), .clk(clock), .clr(clear));        //端口列表中第一项内的信号名是缺省的(空括号)表明端口 q悬空

        模块参数值

                使用带有参数的模块实例语句修改参数值

                        模块名参数值列表调用名(端口名列表)

  1. para l #(4, 3) U1(C1,D1); //利用位置对应方式将4传给a、3传给b,这和模块paral中定义参数的先后顺序有关;
  2. paral #(.b(6), ,a(5)) U2(C2,D2); //利用名称对应方式将6传给b、5传给a,此时和模块paral中定义参数的顺序无关。

                使用参数重定义语句defparam修改参数值      

  1. defparam
  2. 参数名1 =参数值1,
  3. 参数名2 =参数值2,
  4. ...
  5. 参数名n =参数值n;
  1. module halfadder(a, b, s, c); 〃半加器模块 halfadder
  2. input a, b:
  3. output c, s;
  4. parameter xor_delay = 2, and_delay = 3:
  5. assign #xor_delay s = aAb;
  6. assign #and_delay c = a&b;
  7. endmodule
  8. module fulladder(p, q, ci, co, sum); 〃全加器模块 fulladder
  9. input p, q, ci;
  10. output co, sum;
  11. parameter or_delay = 1;
  12. wire wl, w2, w3;
  13. halfadder Ul(p, q, wl, w2);
  14. halfadder U2(ci, w 1, sum, w3);
  15. or #or_delay U3(co, w2, w3);
  16. endmodule
  17. module topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topi
  18. input top la, top lb;
  19. output topis, topic;
  20. defparam U1 .xor_delay = 4,
  21. U1 .and_delay = 5;
  22. //名为U1的半加器实例中对参数xor_delay和参数and_delay值的修改
  23. halfadder Ul(topla, top lb, topis, topic);
  24. endmodule
  25. module top2(top2p, top2q, lop2ci, top2co, top2sum); 〃修改全加器模块参数的模块 top2
  26. input top2p, top2q, top2ci;
  27. output top2co, top2sum;
  28. defparam U2.U1.xor_delay = 6,
  29. U2.U2.and_deIay = 7;
  30. //名为U2的全加器实例中引用的名为U3的半加器实例中对参数xor_delay和
  31. //参数and.delay值的修改
  32. U2.or_delay = 5;
  33. //名为U2的全加器实例中对参数or_delay值的修改
  34. fulladder U2(lop2p, top2q, top2ci, top2co, lop2sum);
  35. endmodule

门级建模

Verilog HDL 中内置有 26 个基本元件 其中 14 个是门级元件 12 个为开关级元件
类型
基本门
多输入门
and, nand, or, nor, xor, xnor
多输出门
buf, not
三态门
允许定义驱动强度
bufif0, bufif 1, notif0, notif1
MOS 开关
无驱动强度
nmos, pmos, emos
rnmos, rpmos, rcmos
双向开关
无驱动强度
tran, tranif0, tranif1
rtran, rtranifO0, rtranif1
上拉 下拉电阻
允许定义驱动强度
pullup, pulldown

         门级模块调用

                多输入门元件

                        元件名<实例名>(<输出端口>,<输入端口 1>,<输入端口 2>, <输入端口 n>)

  1. and Al (outl, ini, in2);
  2. or O2 (a, b, c, d);
  3. xor X1 (x_out, pl, p2);

                多输出门元件

                        元件名<实例名>(<输出端口 1>输出端口 2>,输出端口 n>,输入端口>);

  1. not NOT_1 (outl, out2, in);
  2. buf BUF_1 (bufoutl, bufout2, bufout3, bufin);

                三态门元件

                        元件名<实例名>(<数据输出端口><数据输入端口><控制输入端口>);

  1. bufifl BF1 (data_bus, mem_data, enable);
  2. bufifO BFO (a, b, c);
  3. notifl NT1 (out, in, Ctrl);
  4. notifD NTO (addr, a_bus, select);
        2线 -4线译码器
  1. module decoder2_4(in0, ini, en, outO, outl, out2, out3);
  2. output outO, outl, out2, out3;
  3. input inO, ini, en;
  4. wire wirel, wire2;
  5. not Ul(wirel» inO),
  6. U2(wire2, ini);
  7. nand U3(outO, en, wirel, wire2),
  8. U4(outl, en, wire 1, ini),
  9. U5(out2, en, inO, wire2),
  10. U6(out3, en, inO, ini);
  11. endmodule

开关级建模

        Verilog HDL 提供了十几种开关级基本元件 它们是实际的 MOS 管的抽象表示 这些
开关级基本元件分为两大类 一类是 MOS 开关 一类是双向开关 每一大类又可分为电阻
型(前缀用 r 表示)和非电阻型
        
        MOS开关: nmos pmos cmos
                nmos和pmos开关的实例化语言格式如下:
                        nmos/pmos 实例名(out, data, control)
                coms开关的实例化语言格式如下:
                        cmos 实例名(out, data, ncontrol , pcontrol)
        双向开关:无条件双向开关 (tran)和有条件双向开关 (tranif0 tranif1 )
                tran 实例名 (inoutl > inout2);
                tranifO/tranifl 实例名 (inoutl, inout2, control)

         nmos

  1. module aNMOS(din, ctr, out);
  2. input din, ctr;
  3. output out;
  4. nmos Ul(oul, din, ctr);
  5. endmodule

        2输入与非门的cmos电路

  1. module nnand2(a, b, y);
  2. input a, b;
  3. output y;
  4. supplyO Gnd;
  5. supply1 Vdd: //supplyO 和 supply!为内部参
  6. //量,分别表示低电平和高电平
  7. wire iml;
  8. pmos gl(y, Vdd, a);
  9. pmos g2(y, Vdd, b);
  10. nmos g3(y, iml, a);
  11. nmos g4(iml, Gnd, b);
  12. endmodule

组合电路设计

3个裁判的表决电路

case语句

  1. module design1(OUT, A, B, C);
  2. output OUT;
  3. input A, B, C;
  4. reg OUT;
  5. always @(A or B or C)
  6. case ((A, B, C})
  7. 3'b000:OUT<=0;
  8. 3'b001:OUT<=0;
  9. 3'b010:OUT<=0;
  10. 3'b100:OUT<=0;
  11. 3'b011:OUT<=1;
  12. 3'bl01:OUT<=1;
  13. 3'b110:OUT<=1;
  14. 3'b111:OUT<=1;
  15. endcase

逻辑代数方式

  1. module design2(OUT, A, B, C);
  2. output OUT;
  3. input A, B, C;
  4. assign OUT = (A&B)|(B&C)|(A&C);
  5. endmodule

结构描述方式

  1. module design3(OUT, A, B, C);
  2. output OUT;
  3. input A, B. C;
  4. and U1 (wl, A, B);
  5. and U2 (w2, B, C);
  6. and U3 (w3, A、C);
  7. or U4 (OUT, w 1, w2, w3);
  8. endmodule

抽象描述方式

  1. module design4(OUT, A, B, C);
  2. output OUT;
  3. input A, B, C;
  4. wire [1:0] sum:
  5. reg OUT;
  6. assign sum = A+B+C;
  7. always @(sum)
  8. if(sum>l) OUT = 1:
  9. else OUT = 0;
  10. endmodule

数字加法器

真值表

ABC_INSUMC_OUT
00000
00110
01010
01101
10010
10101
11001
11111

代数逻辑表示为

SUM = A®B® C_IN
C_OUT = AB + (A ® B)C_IN 
  1. /*连续赋值*/
  2. module one_bit_fuiladder(SUM, C_OUT, A, B, C_IN);
  3. input A, B, C_IN;
  4. output SUM, C_OUT;
  5. assign SUM = (A^B)^C_IN;
  6. assign C_OUT = (A&B)|((A^B)&C_IN);
  7. endmodule
  8. /*行为级*/
  9. module one_bit_fulladder(SUM, C_OUT, A, B, C_IN);
  10. output SUM, C_OUT;
  11. input A, B, C_IN;
  12. assign {C_OUT, SUM} = A+B+C_IN;
  13. endmodule

4位超前进位加法器

C1  = G0 + P 0 C 0
C2 = G1| + P1G0 + P1P0C0
C3 = G2 + P2G1 + P2P1G0 + P2P1P0C0
C4 = G3 + P3G2 + P3P2G1 + P3P2P1G0 + P3P2P1P0C0
  1. module four_bits_fast_addder (sum_out, c_out, a, b, c_in);
  2. input [3:0] a, b; //加数,被加数
  3. input c_in; //来自前级的进位
  4. output [3:0] sum_out; 〃和
  5. output c_out; //进位输出
  6. wire [4:0] g, p, c; //产生函数、传输函数和内部进位
  7. assign c[0] = c_in;
  8. assign p = a | b;
  9. assign g = a & b;
  10. assign c[l] = g[0]|(p[0]&c[0]);
  11. assign c[2] = g[1]|(p[1]&(g[0] | (p[0]&c[0])));
  12. assign c[3] = g[2]|(p[2]&(g[1] | (p[1]&(g[0] | (p[0]&c[0])))));
  13. assign c[4] = g[3]|(p[3]&(g[2] | (p[2]&(g[1] | (p[1]&(g[0]|(p[0]&c[0])))))));
  14. assign sum_out = p^c[3:0];
  15. assign c_out = c[4];
  16. endmodule

数据比较器

  1. module four_bits_comp 1 (F, A, B, C);
  2. parameter comp_width = 4;
  3. output [2:0] F;
  4. input [2:0] C;
  5. input [comp_width-1:0] A;
  6. input [comp_width-l:0] B;
  7. reg [2:0] F;
  8. always @(A or B or C)
  9. if(A>B) F= 3'b100;
  10. else if(A<B) F = 3'b001;
  11. else F = C;
  12. endmoduie

数据选择器

  1. module mux8tol_2(d_out, d_in, sei);
  2. output d_out;
  3. input[7:0] d_in;
  4. input[2:0] sel;
  5. wire[3:0] wl;
  6. wire[1:0] w2;
  7. assign w1 = sel[0]? {d_in[7], d_in[5], d_in[3], d_in[1]} :{d_in[6], d_in[4], d_in[2], d_in[0|};
  8. assign w2 = sel[1]? {w1[3], w1[l]}:{w1[2], w1[0]};
  9. assign d_out = sel[2]?w2[1]:w2[0];
  10. endmodule
  11. module mux8tol(out, sel, data_in);
  12. output out;
  13. input [7:0] data_in;
  14. input [3:0] sel;
  15. reg out;
  16. always @ (data_in or sel)
  17. case (sel)
  18. 3'b000 : out <= data_in[0];
  19. 3'b001 : out <= data_in[1];
  20. 3'b010 : out <= daia_in[2];
  21. 3'b011 : out <= data_in[3];
  22. 3'b100 : out <= data_in[4];
  23. 3'b101 : out <= data_in[5];
  24. 3'b110 : out <= data_in[6];
  25. 3'b111 : out <= data_in[7];
  26. endcase
  27. endmodule

数字编码器

  1. module code_8to3(F, I);
  2. output [2:0] F;
  3. input [7:0] I;
  4. reg [2:0] F;
  5. always @ (I)
  6. case (1)
  7. 8'b00000000:F = 3'b000;
  8. 8'b00000010:F = 3'b001;
  9. 8'b00000100:F = 3'b010;
  10. 8,b00001000:F = 3'b011;
  11. 8'b00010000:F = 3'b100;
  12. 8'b00100000:F = 3'b101;
  13. 8'b01000000:F = 3'b110;
  14. 8'bl0000000:F = 3'b111;
  15. default: F = 3'bx;
  16. endcase
  17. endmodule

8线-3线优先编码器

  1. module mux8to3_p(data_out, Ys, Yex, sel, data_in);
  2. output [2:0] data_out;
  3. output Ys, Yex;
  4. input [7:0] clata_in;
  5. input sel;
  6. reg [2:0] data_out;
  7. reg Ys, Yex;
  8. always @ (data_in or sel)
  9. if (sel) (data_out, Ys, Yex} = {3'b111, 1'b1, 1'b1};
  10. else
  11. begin
  12. casex (data_in)
  13. 8'b0???????: {data.out, Ys, Yex} = {3'b000, 1'b1, 1'b0};
  14. 8'bl0??????: {data-out, Ys, Yex} = {3'b001, 1'b1, 1'b0};
  15. 8'b110?????: {daia.out, Ys, Yex} = {3'b010, 1'b1, 1'b0};
  16. 8'b1110????: {data_oul, Ys, Yex} = {3'b011, 1'bl, 1'b0};
  17. 8'b11110???: {data_out, Ys, Yex} = {3'b100, 1'bl, 1'b0);
  18. 8'b111110??: {data_out, Ys, Yex} = {3'b101, 1'bl, 1'b0);
  19. 8'b1111110?: {data_out, Ys, Yex} = {3'b110, 1'bl, 1'b0};
  20. 8'b11111110: {data_out. Ys, Yex} = {3'b111. 1'bl, 1'b0};
  21. 8'b11111111: {data.out, Ys, Yex} = {3'b111, 1'b0, 1'b1);
  22. endcase
  23. end
  24. endmodule

二进制转化十进制8421BCD编码器

 逻辑表达式:

  1. module BCD8421(data_out, data_in);
  2. output [3:0] data_out;
  3. input [8:0] data_in;
  4. reg [3:0] data_out;
  5. always @ (data_in)
  6. case (data_in)
  7. 9'b000000000 : data_out = 4'b0000;
  8. 9'b00000000l : data_out = 4'b0001;
  9. 9'b000000010 : data_out = 4'b0010;
  10. 9'b000000010 : data_out = 4'b0011;
  11. 9'b000001000 : data_out = 4'bO100;
  12. 9'b000010000 : data.out = 4'b0101;
  13. 9'b000100000 : data_out = 4'b0110;
  14. 9'b001000000 : data_out = 4'b0111;
  15. 9'b010000000 : data.out = 4'b1000;
  16. 9'b100000000 : data_out = 4'b1001;
  17. default : data_out = 4'b0000;
  18. endcase
  19. endmodule

8421BCD十进制余3码编码器

  1. module code_change(B_out, B_in);
  2. output [3:0] B_out;
  3. input [3:0] B_in;
  4. assign B_out = B_in+2'b11;
  5. endmodule

数字译码器

2线-4线译码器

  1. module decode_2to4(Y, E, A);
  2. output [3:0] Y:
  3. input [1:0] A;
  4. input E;
  5. assign Y[0] = ~(~E&~A[1]&~A[0]);
  6. assign Y[1] = ~(~E&~A[1]&A[0]);
  7. assign Y[2] = ~(~E&A[1]&~A[0]);
  8. assign Y[3] = ~(~E&A[1]&A[0]);
  9. endmodule
  10. module decode_2tc4(Y, E, A);
  11. output [3:0] Y;
  12. input [1:0] A;
  13. input E;
  14. reg [3:0] Y;
  15. always @(E or A)
  16. case ((E, A))
  17. 3'b1??: Y = 4'b0000;
  18. 3'b000: Y = 4'b0001;
  19. 3'b001: Y = 4'b0010:
  20. 3'b010: Y = 4'b0100;
  21. 3'b011: Y = 4'b1000;
  22. default: Y = 4'b0000;
  23. endcase
  24. endmodule

奇偶校验器

  1. module checker (Fod, Fev, b);
  2. output Fod, Fev;
  3. input [7:0] b;
  4. wire wl, w2, w3, w4, w5, w6;
  5. xor Ul (w1, b[0], b[1]);
  6. xor U2 (w2, b[2], b[3]);
  7. xor U3 (w3, b[4], b[5]);
  8. xor U4 (w4, b[6], b[7]);
  9. xor U5 (w5, wl, w2);
  10. xor U6 (w6, w3, w4);
  11. xor U7 (Fod, w5, w6);
  12. not U8 (Fev, Fod);
  13. endmodule
  14. module checker (Fod, Fev, b);
  15. output Fod, Fev;
  16. input [7:0] b;
  17. assign Fod = ^b;
  18. assign Fev = ~Fod;
  19. endmodule

时序电路设计

 状态图描述

  1. module checker(Z, X, elk);
  2. parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b11, s3 = 2'bl0;
  3. output Z;
  4. input X, clk;
  5. reg [1:0] state, next_state;
  6. reg Z;
  7. always @(X, state)
  8. case (state)
  9. s0:if(X)
  10. begin
  11. next_state <= s1; Z = 0;
  12. end
  13. else
  14. begin
  15. next_state <= s0; Z = 0;
  16. end
  17. s1:if(X)
  18. begin
  19. next_state <= s2; Z = 0;
  20. end
  21. else
  22. begin
  23. next_state <= s0; Z = 0;
  24. end
  25. s2:if(X)
  26. begin
  27. next_state <= s3; Z = 1;
  28. end
  29. else
  30. begin
  31. next_state <= s0; Z = 0;
  32. end
  33. s3:if(X)
  34. begin
  35. next_state <= s3; Z = 1;
  36. end
  37. else
  38. begin
  39. next_state <= s0; Z = 0;
  40. end
  41. endcase
  42. always @(posedge clk)
  43. state <= next_state;
  44. endmodule

化简描述 

  1. //序列检测器模块
  2. module checker (Z, X, clk);
  3. output Z;
  4. inpul X, elk;
  5. wire w1, w2;
  6. DFF U1 (.clk(clk), .D(X), .Q(w1));
  7. DFF U2 (.clk(clk), .D(wl), .Q(w2));
  8. assign Z = X & w1 & w2;
  9. endmodule
  10. //D触发器模块
  11. module DFF (Q, D, clk);
  12. output Q;
  13. input D, clk;
  14. reg Q:
  15. always @(posedge clk) Q <= D;
  16. endmodule

 抽象描述方式

  1. module checker (Z, X, clk);
  2. output Z;
  3. input X. clk;
  4. reg [2:0] q;
  5. reg Z;
  6. always @(posedge clk) q<= {q[10], X};
  7. always @(posedge clk)
  8. if(q=3'blll) Z=1;
  9. else Z = 0;
  10. endmodule

触发器

最简D触发器

  1. module DFF(q, clk, data_in);
  2. output q;
  3. input clk, data_in;
  4. reg q;
  5. always @(posedge clk) q <= data_in;
  6. endmodule

带复位端的D触发器 

  1. module DFF_rst (q, clk, reset, data_in);
  2. output q;
  3. input elk, reset, data_in;
  4. reg q;
  5. always @(posedge clk)
  6. if (!reset) q <= 0;
  7. else q <= data_in;
  8. endmodule

复杂功能的D触发器 

  1. module DFF_l(q, clk, resetl, reset2, data_in);
  2. output q;
  3. input clk, reset1, reset2, data_in;
  4. reg q;
  5. always @(posedge clk)
  6. if (!reset1) q <= 0;
  7. else q <= data_in;
  8. always @(posedge clk or negedge reset2)
  9. if (!reset2) q <= 0;
  10. else q <= data_in;
  11. endmodule

T触发器

  1. module TFF(data_ouL, T, clk, reset);
  2. output data_out;
  3. input T, clk, reset;
  4. reg data_out;
  5. always @(posedge clk or negedge reset)
  6. if (!reset) data_out <= 1'b0;
  7. else if (T) data_out <= ~data_out;
  8. endmodule

计数器

二进制计数器

  1. module comp2bit (Q, clk, reset);
  2. output Q;
  3. input clk, reset;
  4. reg Q;
  5. always @ (posedge clk or negedge reset)
  6. if (!reset)
  7. Q<= 1'b0;
  8. else
  9. Q <= ~Q;
  10. endmodulc

任意进制计数器 

        对于M 进制的计数器 首先应确定计数器所需触发器的个数 N 个触发器对应了 2^ n
个状态 应有 2^ n >M。 任意进制计数器选取满足条件的最小 N, N 为计数器中触发器的个数
        以十一进制计数器为例, 最少需要 4 个触发器。
  1. module comp_11 (count, clk, reset);
  2. output [3:0] count;
  3. input clk, reset;
  4. reg [3:0] count;
  5. always @ (posedge clk)
  6. if(reset) count <= 4'b0000;
  7. else
  8. if (count == 4'b1010)
  9. count <= 4'b0000;
  10. else
  11. count <= count+1;
  12. endmodule

移位寄存器

环形移位寄存器

  1. module shiftregistl (D, clk, reset);
  2. parameter shiftregist_width = 4;
  3. output [shiftregist_widlh-1:0] D;
  4. input clk, reset;
  5. reg [shiftregist_width-1:0] D;
  6. always @(posedge clk)
  7. if (!reset)
  8. D <= 4'b0000;
  9. else
  10. D <= (D[shiftregist_width-2:0], D[shiftregist_width-1]);
  11. endmodule

序列信号发生器

由移位寄存器构成

  1. module signal_maker(out, clk, load, D);
  2. parameter M = 6;
  3. output out;
  4. input clk, load;
  5. input [M-1:0] D;
  6. reg [M-1:0] Q;
  7. initial Q = 6'b100111;
  8. always @(posedge clk)
  9. if (load) Q <= D;
  10. else Q <= {Q[M-2:0], Q[M-1]};
  11. assign out = Q[M-1];
  12. endmodule

由移位寄存器和组合逻辑电路构成 

        首先确定所需移位寄存器的个数nM = 6,故 n>=3。其次确定移位寄存器的6个独立状态按照移位规律每三位一组划分6个状态为 100、001011111, 111110。其中状态111重复出现故取n = 4,并重新划分状态, 得到100100110111111111101100。因此确定n = 4。第三列态序表和反馈激励函数表,求反馈函数F的表达式。

F= ~Q3 + ~Q1 • ~Q0 +Q3+~Q2

  1. module signal_maker(out, clk, load, D);
  2. parameter M = 4;
  3. output out;
  4. input clk, load;
  5. input [M-1 :0] D;
  6. reg [M-1:0] Q;
  7. wire w1;
  8. always @(posedge clk) //时序电路部分,移位寄存器
  9. if (load) Q<=D;
  10. else Q <= {Q[M-2:0], w1};
  11. assign w1 =(~Q[3])|(~Q[1]&(~Q[0]))|(Q[3]&(~Q[2])); //组合逻辑电路,反馈网络
  12. assign out =Q[M-1];
  13. endmodule

由计数器构成

  1. module signal_maker(out, clk, reset);
  2. parameter M = 3;
  3. output out;
  4. input clk, reset;
  5. reg [M-l:0] counter;
  6. always @(posedge clk)
  7. if (!reset) counter <= 3'b000;
  8. else counter <= counter+1;
  9. assign out = counter[2]|((~counter[1])&(~counter[0]))l(counter[1]&counter[0]);
  10. endmodule

有限同步状态机

        Mealy型状态机的输出与当前状态和输入有关
        Moore 型状态机的输出仅依赖于当前状态, 而与输入无关

状态机的编码方式:

  • 二进制编码:其状态寄存器是由触发器组成的
  • 格雷编码:格雷编码状态跳转时只有一个bit(位)发生变化,减少了产生毛刺和一些暂态的可能。
  • 一位独热编码:这是对于n个状态采用n个bit(位)来编码,每个状态编码中只有一个bit(位)为1,如0001、0010、0100、1000。

状态机的两段式描述方法:

  1. //第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
  2. always @(posedge clk or negedge rst_n) //异步复位
  3. if(!rst_n) current_state <= IDLE;
  4. else current_state <= next_state; //注意,使用的是非阻塞赋值
  5. //第二个进程,组合逻辑 always模块,描述状态转移条件判断
  6. always @(current_state or 输入信号) //电平触发
  7. begin
  8. next_state = x; //要初始化,使得系统复位后能进入正确的状态
  9. case(current_state)
  10. Sl:if(...)
  11. next_state = S2; //阻塞赋值
  12. outl <= 1'bl; //注意是非阻塞逻辑
  13. ...
  14. endcase
  15. end

状态机的三段式描述方法:

  1. //第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
  2. always @(posedge clk or negedge rst_n) //异步复位
  3. if(!rst_n) current_state <= IDLE;
  4. else current_state <= next_state; //注意,使用的是非阻塞赋值
  5. //第二个进程,组合逻辑always模块,描述状态转移条件判断
  6. always @(current_state or 输入信号) //电平触发
  7. begin
  8. next_state = x; //要初始化,使得系统复位后能进入正确的状态
  9. case(current_state)
  10. S1: if(...)
  11. next_state = S2; //阻塞赋值
  12. ...
  13. endcase
  14. end
  15. //第三个进程,同步时序always模块,格式化描述次态寄存器输出
  16. always @ (posedge clk or negedge rst_n)
  17. begin
  18. ...//初始化
  19. case(next_state or 输入信号)
  20. S1:
  21. outl <= 1'bl; //注意是非阻塞逻辑
  22. S2:
  23. outl <= 1'b0;
  24. default:... //default的作用是免除综合工具综合出锁存器
  25. endcase
  26. end

4位顺序脉冲发生器

  1. module state4(OUT, clk, rst_n);
  2. output [3:0] OUT:
  3. input clk;
  4. input rst_n;
  5. reg [3:0] OUT;
  6. reg [1:0] STATE, next_STATE;
  7. always @(STATE)
  8. case (STATE)
  9. 2'b00:
  10. begin
  11. OUT <= 4'b11000;
  12. next_STATE <= 2'b01;
  13. 2'b01:
  14. begin
  15. OUT <= 4'b0100;
  16. next_STATE <= 2'b10;
  17. end
  18. 2'b10:
  19. begin
  20. OUT<= 4'b0010;
  21. next_STATE <= 2'b11;
  22. end
  23. 2'bll:
  24. begin
  25. OUT <= 4'b0001;
  26. next_STATE <= 2'b00;
  27. end
  28. endcase
  29. always @(posedge clk or negedge rst_n)
  30. if(!rst_n) STATE <= 2'b00:
  31. else STATE <= next_STATE;
  32. endmodule

 自动售报机

  1. module auto_sellor(current_state, data_out,
  2. data_out_return1, data_out_return2, clk,
  3. rst_n, data_in);
  4. parameter state_width = 3, data_in_width = 3;
  5. output [state_width-1:0] current_state;
  6. output data_out, data_out_return1,
  7. data_out_return2;
  8. input [dala_in_width-1:O] data_in;
  9. input clk, rst_n;
  10. reg [state_width-l:OJ current_state, next_state;
  11. reg data_out, data_out_returnl, data_out_return2;
  12. always @(current_state or data_in)
  13. case (current_state)
  14. 3'b000: case (data_in)
  15. 3'b000: begin
  16. next_state <= 3'b000;
  17. data_out <= 1'b0;
  18. data_out_return1 <= 1'b0;
  19. data_out_return2 <= 1'b0;
  20. end
  21. 3'b001: begin
  22. next_state <= 3'b001;
  23. data_out <= 1'bO;
  24. data_out_return 1 <= 1'bO;
  25. data_out_retum2 <= 1'bO;
  26. end
  27. 3'b010: begin
  28. next_state <= 3'b010;
  29. data_out <= 1'b0;
  30. data_out_return1 <= 1'b0;
  31. data_out_return2 <= 1'b0;
  32. end
  33. 3'b011: begin
  34. next_state <= 3'bl01;
  35. data_out <= 1'bO;
  36. data_out_return 1 <= 1'bO;
  37. data_out_retum2 <= 1'bO;
  38. end
  39. 3'bl00: begin
  40. next_state <= 3'bOOO;
  41. data_out <= 1'bl;
  42. data_out_retum1 <= 1'bO;
  43. data_out_retum2 <= 1'bl;
  44. end
  45. endcase
  46. 3'b001: case (data_in)
  47. 3'b000: begin
  48. next_state <= 3'b001;
  49. data_out <= 1'b0;
  50. data_out_retum1 <= 1'b0;
  51. data_out_retum2 <= 1'b0;
  52. end
  53. 3'b001: begin
  54. next_state <= 3'b010;
  55. data_out <= 1'b0;
  56. data_out_return1 <= 1'b0:
  57. data_out_return2 <= 1'b0;
  58. end
  59. 3'b010: begin
  60. nexl_state <= 3'b011;
  61. data_out <= 1'b0;
  62. data_oul_return1 <= 1'b0;
  63. data_out_return2 <= 1'b0:
  64. end
  65. 3'b011: begin
  66. next_state <= 3'b110;
  67. data_out <= 1'b0;
  68. data_out_return1 <= 1'b0;
  69. data_out_return2 <= 1'b0:
  70. end
  71. endcase
  72. 3'b010: case (daia_in)
  73. 3'b000: begin
  74. next_state <= 3'b010;
  75. data_out <= 1'b0;
  76. data_out_returnl <= 1'b0;
  77. data_out_return2 <= 1'b0;
  78. end
  79. 3'bOO1: begin
  80. next_state <= 3'b011;
  81. data_out <= 1'b0;
  82. data_out_return1 <= 1'b0;
  83. data_oul_return2 <= 1'b0;
  84. end
  85. 3'b010: begin
  86. next_state <= 3'b100;
  87. data_out <= 1'b0;
  88. data_out_return1 <= 1'b0;
  89. data_out_return2 <= 1'b0;
  90. end
  91. 3'b011: begin
  92. next_state <= 3'b111;
  93. data_out <= 1'b0;
  94. data_out_return1 <= 1'b0;
  95. data_out_return2 <= 1'b0;
  96. end
  97. endcase
  98. 3'bO11: case (data_in)
  99. 3'b000: begin
  100. next_state <= 3'b011;
  101. data_out <= 1'b0;
  102. data_out_retuml <= 1'b0;
  103. data_out_return2 <= 1'b0;
  104. end
  105. 3'b001: begin
  106. next_state <= 3'b100;
  107. data_out <= 1'b0;
  108. data_out_return1 <= 1'b0;
  109. data_out_return2 <= 1'b0;
  110. end
  111. 3'b010: begin
  112. next_state <= 3'b101;
  113. data_out <= 1'b0;
  114. data_out_return1 <= 1'b0;
  115. data_out_return2 <= 1'b0;
  116. end
  117. 3'b011: begin
  118. next_state <= 3'b000;
  119. data_out <= 1'b1;
  120. data_out_returnl <= 1'b0;
  121. data_out_return2 <= 1'b0;
  122. end
  123. endcase
  124. 3'blOO: case (data_in)
  125. 3'bOOO: begin
  126. next_state <= 3'b000;
  127. data_out <= 1'b0;
  128. data_out_return1 <= 1'b0;
  129. data_out_return2 <= 1'b0;
  130. end
  131. 31)001: begin
  132. next_state <= 3'b101;
  133. data_out <= 1'b0;
  134. data_out_return1 <= 1'b0;
  135. data_out_return2 <= 1'b0;
  136. end
  137. 3'b010: begin
  138. next_state <= 3'b110;
  139. data_out <= 1'b0;
  140. data_oul_return1 <= 1'b0;
  141. data_out_retumrn2 <= 1'b0;
  142. end
  143. 3'b011: begin
  144. next_state <= 3'b000;
  145. data_out <= 1'b1;
  146. data_out_return1 <= 1'b1;
  147. data_out_return2 <= 1'b0;
  148. end
  149. endcase
  150. 3'b101: case (data_in)
  151. 3'bOOO: begin
  152. next_state <= 3'b101;
  153. data_out <= 1'b0;
  154. data_out_retuml <= 1'b0;
  155. data_out_retum2 <= 1'b0;
  156. end
  157. 3'bOO1: begin
  158. next_state <= 3'b110;
  159. data_out <= 1'b0;
  160. data_out_return1 <= 1'b0;
  161. data_out_return2 <= 1'b0;
  162. end
  163. 3'b010: begin
  164. next_state v= 3'bl 11;
  165. data_out <= 1'bO;
  166. data_out_retum1 <= 1'bO;
  167. data_out_retum2 <= 1'bO;
  168. end
  169. 3'bO11: begin
  170. next_state <= 3'b000;
  171. data_out <= 1'b1;
  172. data_out_return1 <= 1'b0;
  173. data_out_return2 <= 1'b1;
  174. end
  175. endcase
  176. 3'b110: case (data_in)
  177. 3'b000: begin
  178. next_state <= 3'b110:
  179. data_out <= 1'b0;
  180. data_out_return1 <= 1'b0;
  181. data_out_relurn2 <= 1'b0:
  182. end
  183. 3'b001: begin
  184. next_state <= 3'b111;
  185. data_out <= 1'b0;
  186. data_out_relurnl <= 1'bO:
  187. data_out_return2 <= 1'bO;
  188. end
  189. 3'b010: begin
  190. next_state <= 3'bOOO;
  191. data_out <= 1'b1;
  192. data_out_return1 <= 1'bO;
  193. data_out_return2 <= 1'bO;
  194. end
  195. endcase
  196. 3'b111: case (data_in)
  197. 3'bOOO: begin
  198. next_state <= 3'b111;
  199. data_out <= 1'b0;
  200. data_oul_return 1 <= 1'b0;
  201. data_out_retum2 <= 1'b0;
  202. end
  203. 3'bOO1: begin
  204. next_state <= 3'b000;
  205. data_out <= 1'b1;
  206. data_out_retum 1 <= 1'b0;
  207. data_out_return2 <= 1'b0;
  208. end
  209. endcase
  210. endcase
  211. always @(posedge clk or rst_n)
  212. if(!rst_n)
  213. current_state <= 3'bOOO;
  214. else
  215. current_state <= next_state;
  216. endmodule

11010序列检测器

  1. module seqdet (D_out, D_in, rst_n, clk);
  2. parameter IDLE = 3'd0, A = 3'd1,B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5;
  3. output D_out;
  4. input D_in, rst_n, clk;
  5. reg [2:0] state, next_state;
  6. wire D_out;
  7. assign D_out = (state == E)? 1:0;
  8. always @(state or D_in)
  9. case (state)
  10. IDLE : if(D_in) next_state = A;
  11. else next_state = IDLE;
  12. A : if(D_in) next_state = B;
  13. else next_state = IDLE;
  14. B : if(D_in) next_state = B;
  15. else next_state = C;
  16. C : if (D_in) next_state = D;
  17. else next_state = IDLE;
  18. D : if (D_in) next_state = B;
  19. else next_state = E;
  20. E : if (D_in) next_state = IDLE;
  21. else next_state = A;
  22. default: next_state = IDLE;
  23. endcase
  24. always @(posedge clk)
  25. state <= next_state;
  26. endmodule

电路仿真和测试程序

语言要素

 $display $write

        $display("<format_specifiers>“, <signal1, signa!2, signaln>);

        $write("<format_specifiers>", <signal 1, signal2,signaln>);

 $monitor $strobe

        $monitor("<format_specifiers>", <signall, signa!2, signaln>);
        $strobe(<functions_or_signals>);
        $strobe(” <string_and/or_variables> , <functions_or_signals>);
                $strobe—在所有时间处理完后,以十进制格式输出一行格式化的文本
                $strobeb—— 在所有时间处理完后 以二进制格式输出一行格式化的文本
                $strobeo—— 在所有时间处理完后 以八进制格式输出一行格式化的文本
                $strobeh—在所有时间处理完后, 以十六进制格式输出一行格式化的文本

$time $realtime

        这两个函数被调用后都返回当前时刻相对仿真开始时刻的时间量值。 所不同的是 $time 函数以 64 位整数值的形式返回仿真时间 $realtime 函数则以实型数据的形式返回仿真时间。
$finish $stop
        $finish;
        $finish(n);
        $stop;
        $stop(n);

$readmemh $readmemb

        $readmemb("<file_name>", <memory_name>);
        $readmemb("<file_name>",<memory_name>, <start_addr>);
        $readmemb("<file_name >",<memory_name>, <start_addr>, <finish_addr>);
        $readmemh("<file_name >", <memory_name>);
        $readmemh("<file_name >", <memoi-y_name>, <stail_addr>);
        $readmemh("<file_name >", <memory_name>, <start_addr>, <finish_addr>);

$random

        $random%<number>;        //时返回一个 32 bit 的随机数

VCD

十进制加法器

  1. module cntl0(clk, rst, ena, q, cout);
  2. input clk, rst, ena;
  3. output[3:0] q;
  4. output cout;
  5. reg[3:0] q;
  6. always @ (posedge clk or posedge rst)
  7. begin
  8. if(rst)q = 4'b0000;
  9. else if(ena)
  10. begin
  11. if(q<9)q = q+1;
  12. else q = 0;
  13. end
  14. end
  15. assign cout = q[3]&q[0];
  16. endmodule
  17. module cnt10_tb;
  18. reg clk, rst, ena;
  19. wire [3:0] q;
  20. wire cout;
  21. cnt_10 U1(clk, rst, ena, q, cout); //模块实例化
  22. always #50 elk = ~clk; //时钟信号产生
  23. initial
  24. begin
  25. clk = 0; rst = 0; ena = 1; //控制信号产生
  26. #1200 rst= 1;
  27. #120 rst = 0;
  28. #2000 ena = 0;
  29. #200 ena = 1;
  30. #20000 $finish;
  31. end
  32. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/933731
推荐阅读
相关标签
  

闽ICP备14008679号