赞
踩
目录
本文将涉及verilog的设计方法,探索使用verilog hdl描述数字电路,探索verilog的语言特性。
内容总结于诚聘英才 > 在线课堂_西安电子科技大学微电子学院
【电子】Verilog硬件描述语言 西安电子科技大学 蔡觉平等主讲_哔哩哔哩_bilibili
状态
|
含义
|
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^
?
、
_
|
注意事项:
标记符
|
名称
|
类型
|
强弱程度
|
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
| x | z |
0
| 0 | x | x | 0 |
1
| x | 1 | x | 1 |
x | x | x | x | x |
z | 0 | 1 | x | z |
寄存器型:reg型:数据储存单元的抽象类型,能够存储数据,如触发器、锁存器等,
reg型变量:常用于行为级描述中,由过程赋值语句对其进行赋值。
格式:reg<range><list_of_register_variables>;
存储器型:存储器型(memory)本质上还是寄存器型变量阵列,存储器型变量可以描述RAM型、ROM型存储器以及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 |
注意事项:
== | 0 | 1 | x | z |
0 | 1 | 0 | x | x |
1 | 0 | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
===:
=== | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
逻辑运算符:
a | b | !a | !b | a&&b | a||b |
1 | 1 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 0 | 1 |
0 | 0 | 1 | 1 | 0 | 0 |
按位运算符:
&:
& | 0 | 1 | x |
0 | 0 | 0 | 0 |
1 | 0 | 1 | x |
x | 0 | x | x |
|:
| | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 1 | 1 |
x | x | 1 | x |
^:
^ | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 0 | x |
x | x | x | x |
两个不同长度的数据进行位运算时,会自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐,然后逐位进行运算,运算结果的位宽与操作数中位宽较大者相同。
缩位运算符包括&(与)、I (或)、^(异或)以及相应的非操作~&、~|、~^、^~。
归约运算符的操作数只有一个。
左移位运算符(<<)、右移位运算符(>>)。
<条件表达式>?<表达式1>:<表达式2>
条件表达式的运算结果有真(1)、假(0)和不定态(x)三种。当条件表达式的结果为真时,
如果条件表达式的运算结果为不定态x,则模拟器将按位对表达式1的值与表达式2的值
?: | 0 | 1 | x | z |
0 | 0 | x | x | x |
1 | x | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
连接运算符 {} :{信号1的某几位,信号2的某几位,信号n的某几位}。
复制运算符 {{}} :将一个表达式放入双重花括号中,复制因子放在第一层括号中。
声明方式:
输入端口: input[倩号位宽-1:0]端口名1;
输出端口: output[信号位宽-1:0]端口名1:
输入瀚出端口: inout[信号位宽-1:0]端口名1;
模块引用时端口的对应方式:
模块名(连接端口 1信号名,连接端口 2信号名…);
过程语句 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过程块在进行仿真时从模拟0时刻开始执行,它在仿真过程中只执行一次,在执
- initial
- begin
- 语句I;
- 语句2;
- 语句n;
- end
- module initial_tb1:
- reg A, B, C;
- initial
- begin
- A = 0;B= 1;C = O;
- #100 A= 1; B = 0;
- #100 A = 0;C= I;
- #100 B = 1;
- #100 B = 0; C = 0;
- end
- endmodule
- always@(<敏感事件列表>)
- 语句块;
-
- @(a) //当信号a的值发生改变时
- @(a or b) //当信号a或信号b的值发生改变时
- @(posedge clock) //当clock的上升沿到来时
- @(negedge clock) //当clock的下降沿到来时
- @(posedge elk or negedge reset) //当clk的上升沿到来或reset信号的下降沿(低电平有效)到来时
注意事项:
四选一数据选择器
- /*四选一数据选择器*/
- module mux4_l(out, in0, in1, in2, in3, sel):
- output out;
- input in0, ini, in2, in3;
- inpul[1 :0] sel;
- reg out; 〃被赋值信号定义为“reg”类型
- always @(in0 or ini or in2 or in3 or sel) 〃敏感事件列表
- case(sel)
- 2'b00: out = inO;
- 2'b01: out = ini;
- 2'b10: out = in2;
- Z'b11: out = in3;
- default: out = 2'bx;
- endcase
- endmodule
同步置数、同步清零计数器:
- module counter 1 (out, data, load, rst, elk);
- output[7:0] out;
- input[7:0] data;
- input load, elk, rst;
- reg[7:0] out;
- always @(posedge elk) //clk上升沿触发
- begin
- if(!rst) out = 8'h00; //同步清零,低电平有效
- else if(load) out = data; //同步置数
- else out = out+ 1;
- end
- endmodule
异步清零计数器:
- module counter2(rst, elk, out);
- output[7:0] out;
- input elk, rst;
- reg[7:0] out;
- always @(posedge clk or negedge rst) // clk 上升沿和 rst 低电平清零有效
- begin
- if(!rst) //异步清零
- out = 0;
- else out = out+1;
- end
- endmodule
串行语句块:其中的语句按串行方式顺序执行,可以用于可综合电路程序和仿真测试程序
块名即该块的名字,当块内有变量时必须有块名,否则在编译时将出现语法错误。块内声明语句是可选的,可以是参数说明语句‘integer型变量声明语句、reg型变量声明语句、time型变量声明语句和事件(event)说明语句。
- begin:块名
- 块内声明语句;
- 语句1;
- 语句2;
- ...
- 语句n;
- end
并行语句块:语句按并行方式执行,只能用于仿真测试程序,不能用于可综合电路程序。
- fork:块名
- 块内声明语句:
- 语句1;
- 语句2;
- ...
- 语句n;
- join
两者比较:
语句块
|
串行语句块
(begin-cnd)
|
并行语句块
(fork-join)
|
执行顺序
|
按照语句顺序执行
|
所有语句均在同一时刻执行
|
语句前面延迟
时间的意义
|
相对于前一条语句执行结束的相对时间
|
相对于并行语句块启动的时间
|
起始时间
|
首句开始执行的时间
|
转入并行语句块的时间
|
结束时间
|
最后一条语句执行结束的时间
|
执行时间最长的那条语句执行 结束的时间
|
行为描述的 意义
|
电路中的数据在时钟及控制信号的作用下
, 沿数据通道中各级寄存器之间传送的过程
|
电路上电后
,
各电路模块同时开始工作的过程
|
阻塞赋值语句:变量=表达式;
当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成,则后面的语句就不能被执行,仿佛被阻塞了一样,因此称为阻塞赋值方式。
特点:
在串行语句块中,各条阻塞赋值语句将按照排列顺序依次执行;在并行语句块中的各条阻塞赋值语句则同时执行,没有先后之分。
执行阻塞赋值语句的顺序是,先计算等号右端表达式的值,然后立刻将计算的值赋给左边的变量,与仿真时间无关。
非阻塞赋值语句 :变量 <=表达式;
特点:
在串行语句块中,各条非阻塞赋值语句的执行没有先后之分,排在前面的语句不会影响到后面语句的执行,各条语句并行执行。
执行非阻塞赋值语句的顺序是,先计算右端表达式的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。
赋值语句和重新赋值语句:assign deassign:使用assign给寄存器型变量赋值之后,该值将一直保 持在这个寄存器上,直至遇到deassign。
assign <寄存器型变量>=<赋值表达式>;
deassign<寄存器型变量>;
强制语句和释放语句:force release:主要用于Verilog HDL仿真测试程序中,便于对某种信号进行临时性的赋值和测试。
force <寄存器或连线型变量>=<赋值表达式>;
release<寄存器或连线型变量>;
if语句:
- if(条件表达式)语句块; //form 1
-
-
- if(条件表达式) //form 2
- 语句块1;
- else
- 语句块2;
-
- if(条件表达式1) //form 3
- 语句块1;
- else if(条件表达式2)
- 语句块2;
- ...
- else if(条件表达式i)
- 语句块i;
- else
- 语句块n;
case语句:
- case(控制表达式)
- 值1:语句块1
- 值2:语句块2
- ...
- 值n:语句块n
- default:语句块 n+l
- endcase
case语句的真值表:
case | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
BCD数码管译码:
- module BCD_decoder(out, in);
- output[6:0]out;
- input[3:0]in;
- reg[6:0]out;
- always@(in)
- begin
- case(in)
- 4'b0000:out = 7'b1111110;
- 4'b0001:out = 7'b0110000;
- 4'b0010:out = 7'b1101101;
- 4'b0011:out = 7'b1111001;
- 4'b0100:out = 7'b0110011;
- 4'b0101:out = 7'b1011011;
- 4'b0110:out = 7'b1011111;
- 4'b0111:out = 7'b1110000;
- 4'bl000:out = 7'blllllll;
- 4'bl001:out = 7'bllll011;
- default:out = 7'bx;
- endcase
- end
- endmodule
casez:比较双方有一位为z,即认为这一位永远为真
casez | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 1 |
x | 0 | 0 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
casex:比较双方有一位为x或z,即认为这一位永远为真
casex | 0 | 1 | x | z |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 1 | 1 | 1 |
x | 1 | 1 | 1 | 1 |
z | 1 | 1 | 1 | 1 |
forever 语句
forever 语句或语句块;
- module forever_tb;
- reg clock;
- initial
- begin
- clock = 0;
- forever #50clock = ~clock;
- end
- endmodule
repeat 语句
- repeat(循环次数表达式)
- 语句或语句块(循环体)
- module repeat_tb; //使用repeat语句产生固定周期数的时钟信号。
- reg clock;
- inilial
- begin
- clock = 0;
- repeat(8) clock = -clock; //循环体所预先制定的循环次数为8次,相应产生4个时钟周期信号
- end
- endmodule
while 语句
while(条件表达式)语句或语句块;
- module while_tb;
- reg clock;
- initial
- begin
- clock = 0;
- while(l)
- #50 clock = ~clock;
- end
- endmodule
for语句
for(循环变量赋初值:循环结束条件:循环变量增值)语句块;
- module for_clk;
- reg cik;
- integer i;
- initial
- begin
- elk = 0;
- for(i = 0; i >= 0: i = i+1)
- #50 elk = ~clk;
- end
- endmodule
8位移位寄存器
- //采用赋值语句实现
- module shift_registl(Q, D, rst, elk);
- output [7:0] Q;
- input D, rst, elk:
- reg [7:0] Q;
- always @(posedge elk)
- if(!rst) Q <= 8'b000000;
- else Q <= {Q[6:0], D};
- endmodule
-
- //采用for语句实现
- module shift_regist2(Q, D, rst, elk);
- output [7:0] Q;
- input D, rst, elk;
- reg [7:0] Q;
- integer i;
- always @(posedge elk)
- if(!rst)Q<= 8'b000000;
- else
- begin
- for (i = 7; i > 0; i = i-1) Q[i] <= Q[i-1];
- Q[0] <= D;
- end
- endmodule
模块名〈参数值列表〉实例名(端口名列表);
端口位置对应方式
模块名〈参数值列表〉实例名(<信号名1>. <信号名2>, …,<信号名n>);
端口名对应方式
模块名〈参数值列表〉实例名(.端口名1<信号名1>, .端口名2<信号名2>, …,.端口名n<信号名 n>):
dff U4(.q(), ,d(out[2]), .clk(clock), .clr(clear)); //端口列表中第一项内的信号名是缺省的(空括号),表明端口 “q”悬空。
使用带有参数的模块实例语句修改参数值
模块名〈参数值列表〉调用名(端口名列表);
- para l #(4, 3) U1(C1,D1); //利用位置对应方式将4传给a、3传给b,这和模块paral中定义参数的先后顺序有关;
- paral #(.b(6), ,a(5)) U2(C2,D2); //利用名称对应方式将6传给b、5传给a,此时和模块paral中定义参数的顺序无关。
使用参数重定义语句defparam修改参数值
- defparam
- 参数名1 =参数值1,
- 参数名2 =参数值2,
- ...
- 参数名n =参数值n;
- module halfadder(a, b, s, c); 〃半加器模块 halfadder
- input a, b:
- output c, s;
- parameter xor_delay = 2, and_delay = 3:
- assign #xor_delay s = aAb;
- assign #and_delay c = a&b;
- endmodule
- module fulladder(p, q, ci, co, sum); 〃全加器模块 fulladder
- input p, q, ci;
- output co, sum;
- parameter or_delay = 1;
- wire wl, w2, w3;
- halfadder Ul(p, q, wl, w2);
- halfadder U2(ci, w 1, sum, w3);
- or #or_delay U3(co, w2, w3);
- endmodule
-
- module topi(topla, top lb, topis, topic); 〃修改半加器模块参数的模块 topi
- input top la, top lb;
- output topis, topic;
- defparam U1 .xor_delay = 4,
- U1 .and_delay = 5;
- //名为U1的半加器实例中对参数xor_delay和参数and_delay值的修改
- halfadder Ul(topla, top lb, topis, topic);
- endmodule
- module top2(top2p, top2q, lop2ci, top2co, top2sum); 〃修改全加器模块参数的模块 top2
- input top2p, top2q, top2ci;
- output top2co, top2sum;
- defparam U2.U1.xor_delay = 6,
- U2.U2.and_deIay = 7;
- //名为U2的全加器实例中引用的名为U3的半加器实例中对参数xor_delay和
- //参数and.delay值的修改
- U2.or_delay = 5;
- //名为U2的全加器实例中对参数or_delay值的修改
- fulladder U2(lop2p, top2q, top2ci, top2co, lop2sum);
- endmodule
类型 |
元
件
| |
基本门
|
多输入门
|
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>);
- and Al (outl, ini, in2);
- or O2 (a, b, c, d);
- xor X1 (x_out, pl, p2);
多输出门元件
元件名<实例名>(<输出端口 1>,<输出端口 2>,…,〈输出端口 n>,〈输入端口>);
- not NOT_1 (outl, out2, in);
- buf BUF_1 (bufoutl, bufout2, bufout3, bufin);
三态门元件
元件名<实例名>(<数据输出端口>,<数据输入端口>,<控制输入端口>);
- bufifl BF1 (data_bus, mem_data, enable);
- bufifO BFO (a, b, c);
- notifl NT1 (out, in, Ctrl);
- notifD NTO (addr, a_bus, select);
- module decoder2_4(in0, ini, en, outO, outl, out2, out3);
- output outO, outl, out2, out3;
- input inO, ini, en;
- wire wirel, wire2;
- not Ul(wirel» inO),
- U2(wire2, ini);
- nand U3(outO, en, wirel, wire2),
- U4(outl, en, wire 1, ini),
- U5(out2, en, inO, wire2),
- U6(out3, en, inO, ini);
- endmodule
nmos
- module aNMOS(din, ctr, out);
- input din, ctr;
- output out;
- nmos Ul(oul, din, ctr);
- endmodule
2输入与非门的cmos电路
- module nnand2(a, b, y);
- input a, b;
- output y;
- supplyO Gnd;
- supply1 Vdd: //supplyO 和 supply!为内部参
- //量,分别表示低电平和高电平
- wire iml;
- pmos gl(y, Vdd, a);
- pmos g2(y, Vdd, b);
- nmos g3(y, iml, a);
- nmos g4(iml, Gnd, b);
- endmodule
- module design1(OUT, A, B, C);
- output OUT;
- input A, B, C;
- reg OUT;
- always @(A or B or C)
- case ((A, B, C})
- 3'b000:OUT<=0;
- 3'b001:OUT<=0;
- 3'b010:OUT<=0;
- 3'b100:OUT<=0;
- 3'b011:OUT<=1;
- 3'bl01:OUT<=1;
- 3'b110:OUT<=1;
- 3'b111:OUT<=1;
- endcase
- module design2(OUT, A, B, C);
- output OUT;
- input A, B, C;
- assign OUT = (A&B)|(B&C)|(A&C);
- endmodule
- module design3(OUT, A, B, C);
- output OUT;
- input A, B. C;
- and U1 (wl, A, B);
- and U2 (w2, B, C);
- and U3 (w3, A、C);
- or U4 (OUT, w 1, w2, w3);
- endmodule
- module design4(OUT, A, B, C);
- output OUT;
- input A, B, C;
- wire [1:0] sum:
- reg OUT;
- assign sum = A+B+C;
- always @(sum)
- if(sum>l) OUT = 1:
- else OUT = 0;
- endmodule
A | B | C_IN | SUM | C_OUT |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
- /*连续赋值*/
- module one_bit_fuiladder(SUM, C_OUT, A, B, C_IN);
- input A, B, C_IN;
- output SUM, C_OUT;
- assign SUM = (A^B)^C_IN;
- assign C_OUT = (A&B)|((A^B)&C_IN);
- endmodule
-
-
- /*行为级*/
- module one_bit_fulladder(SUM, C_OUT, A, B, C_IN);
- output SUM, C_OUT;
- input A, B, C_IN;
- assign {C_OUT, SUM} = A+B+C_IN;
- endmodule
- module four_bits_fast_addder (sum_out, c_out, a, b, c_in);
- input [3:0] a, b; //加数,被加数
- input c_in; //来自前级的进位
- output [3:0] sum_out; 〃和
- output c_out; //进位输出
- wire [4:0] g, p, c; //产生函数、传输函数和内部进位
- assign c[0] = c_in;
- assign p = a | b;
- assign g = a & b;
- assign c[l] = g[0]|(p[0]&c[0]);
- assign c[2] = g[1]|(p[1]&(g[0] | (p[0]&c[0])));
- assign c[3] = g[2]|(p[2]&(g[1] | (p[1]&(g[0] | (p[0]&c[0])))));
- assign c[4] = g[3]|(p[3]&(g[2] | (p[2]&(g[1] | (p[1]&(g[0]|(p[0]&c[0])))))));
- assign sum_out = p^c[3:0];
- assign c_out = c[4];
- endmodule
- module four_bits_comp 1 (F, A, B, C);
- parameter comp_width = 4;
- output [2:0] F;
- input [2:0] C;
- input [comp_width-1:0] A;
- input [comp_width-l:0] B;
- reg [2:0] F;
- always @(A or B or C)
- if(A>B) F= 3'b100;
- else if(A<B) F = 3'b001;
- else F = C;
- endmoduie
- module mux8tol_2(d_out, d_in, sei);
- output d_out;
- input[7:0] d_in;
- input[2:0] sel;
- wire[3:0] wl;
- wire[1:0] w2;
- 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|};
- assign w2 = sel[1]? {w1[3], w1[l]}:{w1[2], w1[0]};
- assign d_out = sel[2]?w2[1]:w2[0];
- endmodule
-
-
- module mux8tol(out, sel, data_in);
- output out;
- input [7:0] data_in;
- input [3:0] sel;
- reg out;
- always @ (data_in or sel)
- case (sel)
- 3'b000 : out <= data_in[0];
- 3'b001 : out <= data_in[1];
- 3'b010 : out <= daia_in[2];
- 3'b011 : out <= data_in[3];
- 3'b100 : out <= data_in[4];
- 3'b101 : out <= data_in[5];
- 3'b110 : out <= data_in[6];
- 3'b111 : out <= data_in[7];
- endcase
- endmodule
- module code_8to3(F, I);
- output [2:0] F;
- input [7:0] I;
- reg [2:0] F;
- always @ (I)
- case (1)
- 8'b00000000:F = 3'b000;
- 8'b00000010:F = 3'b001;
- 8'b00000100:F = 3'b010;
- 8,b00001000:F = 3'b011;
- 8'b00010000:F = 3'b100;
- 8'b00100000:F = 3'b101;
- 8'b01000000:F = 3'b110;
- 8'bl0000000:F = 3'b111;
- default: F = 3'bx;
- endcase
- endmodule
- module mux8to3_p(data_out, Ys, Yex, sel, data_in);
- output [2:0] data_out;
- output Ys, Yex;
- input [7:0] clata_in;
- input sel;
- reg [2:0] data_out;
- reg Ys, Yex;
- always @ (data_in or sel)
- if (sel) (data_out, Ys, Yex} = {3'b111, 1'b1, 1'b1};
- else
- begin
- casex (data_in)
- 8'b0???????: {data.out, Ys, Yex} = {3'b000, 1'b1, 1'b0};
- 8'bl0??????: {data-out, Ys, Yex} = {3'b001, 1'b1, 1'b0};
- 8'b110?????: {daia.out, Ys, Yex} = {3'b010, 1'b1, 1'b0};
- 8'b1110????: {data_oul, Ys, Yex} = {3'b011, 1'bl, 1'b0};
- 8'b11110???: {data_out, Ys, Yex} = {3'b100, 1'bl, 1'b0);
- 8'b111110??: {data_out, Ys, Yex} = {3'b101, 1'bl, 1'b0);
- 8'b1111110?: {data_out, Ys, Yex} = {3'b110, 1'bl, 1'b0};
- 8'b11111110: {data_out. Ys, Yex} = {3'b111. 1'bl, 1'b0};
- 8'b11111111: {data.out, Ys, Yex} = {3'b111, 1'b0, 1'b1);
- endcase
- end
- endmodule
逻辑表达式:
- module BCD8421(data_out, data_in);
- output [3:0] data_out;
- input [8:0] data_in;
- reg [3:0] data_out;
- always @ (data_in)
- case (data_in)
- 9'b000000000 : data_out = 4'b0000;
- 9'b00000000l : data_out = 4'b0001;
- 9'b000000010 : data_out = 4'b0010;
- 9'b000000010 : data_out = 4'b0011;
- 9'b000001000 : data_out = 4'bO100;
- 9'b000010000 : data.out = 4'b0101;
- 9'b000100000 : data_out = 4'b0110;
- 9'b001000000 : data_out = 4'b0111;
- 9'b010000000 : data.out = 4'b1000;
- 9'b100000000 : data_out = 4'b1001;
- default : data_out = 4'b0000;
- endcase
- endmodule
- module code_change(B_out, B_in);
- output [3:0] B_out;
- input [3:0] B_in;
- assign B_out = B_in+2'b11;
- endmodule
- module decode_2to4(Y, E, A);
- output [3:0] Y:
- input [1:0] A;
- input E;
- assign Y[0] = ~(~E&~A[1]&~A[0]);
- assign Y[1] = ~(~E&~A[1]&A[0]);
- assign Y[2] = ~(~E&A[1]&~A[0]);
- assign Y[3] = ~(~E&A[1]&A[0]);
- endmodule
-
-
- module decode_2tc4(Y, E, A);
- output [3:0] Y;
- input [1:0] A;
- input E;
- reg [3:0] Y;
- always @(E or A)
- case ((E, A))
- 3'b1??: Y = 4'b0000;
- 3'b000: Y = 4'b0001;
- 3'b001: Y = 4'b0010:
- 3'b010: Y = 4'b0100;
- 3'b011: Y = 4'b1000;
- default: Y = 4'b0000;
- endcase
- endmodule
- module checker (Fod, Fev, b);
- output Fod, Fev;
- input [7:0] b;
- wire wl, w2, w3, w4, w5, w6;
- xor Ul (w1, b[0], b[1]);
- xor U2 (w2, b[2], b[3]);
- xor U3 (w3, b[4], b[5]);
- xor U4 (w4, b[6], b[7]);
- xor U5 (w5, wl, w2);
- xor U6 (w6, w3, w4);
- xor U7 (Fod, w5, w6);
- not U8 (Fev, Fod);
- endmodule
-
-
- module checker (Fod, Fev, b);
- output Fod, Fev;
- input [7:0] b;
- assign Fod = ^b;
- assign Fev = ~Fod;
- endmodule
- module checker(Z, X, elk);
- parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b11, s3 = 2'bl0;
- output Z;
- input X, clk;
- reg [1:0] state, next_state;
- reg Z;
- always @(X, state)
- case (state)
- s0:if(X)
- begin
- next_state <= s1; Z = 0;
- end
- else
- begin
- next_state <= s0; Z = 0;
- end
- s1:if(X)
- begin
- next_state <= s2; Z = 0;
- end
- else
- begin
- next_state <= s0; Z = 0;
- end
- s2:if(X)
- begin
- next_state <= s3; Z = 1;
- end
- else
- begin
- next_state <= s0; Z = 0;
- end
- s3:if(X)
- begin
- next_state <= s3; Z = 1;
- end
- else
- begin
- next_state <= s0; Z = 0;
- end
- endcase
- always @(posedge clk)
- state <= next_state;
- endmodule
- //序列检测器模块
- module checker (Z, X, clk);
- output Z;
- inpul X, elk;
- wire w1, w2;
- DFF U1 (.clk(clk), .D(X), .Q(w1));
- DFF U2 (.clk(clk), .D(wl), .Q(w2));
- assign Z = X & w1 & w2;
- endmodule
-
- //D触发器模块
- module DFF (Q, D, clk);
- output Q;
- input D, clk;
- reg Q:
- always @(posedge clk) Q <= D;
- endmodule
- module checker (Z, X, clk);
- output Z;
- input X. clk;
- reg [2:0] q;
- reg Z;
- always @(posedge clk) q<= {q[1:0], X};
- always @(posedge clk)
- if(q=3'blll) Z=1;
- else Z = 0;
- endmodule
- module DFF(q, clk, data_in);
- output q;
- input clk, data_in;
- reg q;
- always @(posedge clk) q <= data_in;
- endmodule
- module DFF_rst (q, clk, reset, data_in);
- output q;
- input elk, reset, data_in;
- reg q;
- always @(posedge clk)
- if (!reset) q <= 0;
- else q <= data_in;
- endmodule
- module DFF_l(q, clk, resetl, reset2, data_in);
- output q;
- input clk, reset1, reset2, data_in;
- reg q;
- always @(posedge clk)
- if (!reset1) q <= 0;
- else q <= data_in;
- always @(posedge clk or negedge reset2)
- if (!reset2) q <= 0;
- else q <= data_in;
- endmodule
- module TFF(data_ouL, T, clk, reset);
- output data_out;
- input T, clk, reset;
- reg data_out;
- always @(posedge clk or negedge reset)
- if (!reset) data_out <= 1'b0;
- else if (T) data_out <= ~data_out;
- endmodule
- module comp2bit (Q, clk, reset);
- output Q;
- input clk, reset;
- reg Q;
- always @ (posedge clk or negedge reset)
- if (!reset)
- Q<= 1'b0;
- else
- Q <= ~Q;
- endmodulc
- module comp_11 (count, clk, reset);
- output [3:0] count;
- input clk, reset;
- reg [3:0] count;
- always @ (posedge clk)
- if(reset) count <= 4'b0000;
- else
- if (count == 4'b1010)
- count <= 4'b0000;
- else
- count <= count+1;
- endmodule
- module shiftregistl (D, clk, reset);
- parameter shiftregist_width = 4;
- output [shiftregist_widlh-1:0] D;
- input clk, reset;
- reg [shiftregist_width-1:0] D;
- always @(posedge clk)
- if (!reset)
- D <= 4'b0000;
- else
- D <= (D[shiftregist_width-2:0], D[shiftregist_width-1]);
- endmodule
- module signal_maker(out, clk, load, D);
- parameter M = 6;
- output out;
- input clk, load;
- input [M-1:0] D;
- reg [M-1:0] Q;
- initial Q = 6'b100111;
- always @(posedge clk)
- if (load) Q <= D;
- else Q <= {Q[M-2:0], Q[M-1]};
- assign out = Q[M-1];
- endmodule
首先确定所需移位寄存器的个数n。因M = 6,故 n>=3。其次确定移位寄存器的6个独立状态。按照移位规律每三位一组,划分6个状态为 100、001、011、111, 111、110。其中状态111重复出现,故取n = 4,并重新划分状态, 得到1001、0011、0111、1111、1110、1100。因此确定n = 4。第三,列态序表和反馈激励函数表,求反馈函数F的表达式。
F= ~Q3 + ~Q1 • ~Q0 +Q3+~Q2
- module signal_maker(out, clk, load, D);
- parameter M = 4;
- output out;
- input clk, load;
- input [M-1 :0] D;
- reg [M-1:0] Q;
- wire w1;
- always @(posedge clk) //时序电路部分,移位寄存器
- if (load) Q<=D;
- else Q <= {Q[M-2:0], w1};
- assign w1 =(~Q[3])|(~Q[1]&(~Q[0]))|(Q[3]&(~Q[2])); //组合逻辑电路,反馈网络
- assign out =Q[M-1];
- endmodule
- module signal_maker(out, clk, reset);
- parameter M = 3;
- output out;
- input clk, reset;
- reg [M-l:0] counter;
- always @(posedge clk)
- if (!reset) counter <= 3'b000;
- else counter <= counter+1;
- assign out = counter[2]|((~counter[1])&(~counter[0]))l(counter[1]&counter[0]);
- endmodule
- //第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
- always @(posedge clk or negedge rst_n) //异步复位
- if(!rst_n) current_state <= IDLE;
- else current_state <= next_state; //注意,使用的是非阻塞赋值
- //第二个进程,组合逻辑 always模块,描述状态转移条件判断
- always @(current_state or 输入信号) //电平触发
- begin
- next_state = x; //要初始化,使得系统复位后能进入正确的状态
- case(current_state)
- Sl:if(...)
- next_state = S2; //阻塞赋值
- outl <= 1'bl; //注意是非阻塞逻辑
- ...
- endcase
- end
- //第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
- always @(posedge clk or negedge rst_n) //异步复位
- if(!rst_n) current_state <= IDLE;
- else current_state <= next_state; //注意,使用的是非阻塞赋值
- //第二个进程,组合逻辑always模块,描述状态转移条件判断
- always @(current_state or 输入信号) //电平触发
- begin
- next_state = x; //要初始化,使得系统复位后能进入正确的状态
- case(current_state)
- S1: if(...)
- next_state = S2; //阻塞赋值
- ...
- endcase
- end
- //第三个进程,同步时序always模块,格式化描述次态寄存器输出
- always @ (posedge clk or negedge rst_n)
- begin
- ...//初始化
- case(next_state or 输入信号)
- S1:
- outl <= 1'bl; //注意是非阻塞逻辑
- S2:
- outl <= 1'b0;
- default:... //default的作用是免除综合工具综合出锁存器
- endcase
- end
- module state4(OUT, clk, rst_n);
- output [3:0] OUT:
- input clk;
- input rst_n;
- reg [3:0] OUT;
- reg [1:0] STATE, next_STATE;
- always @(STATE)
- case (STATE)
- 2'b00:
- begin
- OUT <= 4'b11000;
- next_STATE <= 2'b01;
- 2'b01:
- begin
- OUT <= 4'b0100;
- next_STATE <= 2'b10;
- end
- 2'b10:
- begin
- OUT<= 4'b0010;
- next_STATE <= 2'b11;
- end
- 2'bll:
- begin
- OUT <= 4'b0001;
- next_STATE <= 2'b00;
- end
- endcase
- always @(posedge clk or negedge rst_n)
- if(!rst_n) STATE <= 2'b00:
- else STATE <= next_STATE;
- endmodule
- module auto_sellor(current_state, data_out,
- data_out_return1, data_out_return2, clk,
- rst_n, data_in);
- parameter state_width = 3, data_in_width = 3;
- output [state_width-1:0] current_state;
- output data_out, data_out_return1,
- data_out_return2;
- input [dala_in_width-1:O] data_in;
- input clk, rst_n;
- reg [state_width-l:OJ current_state, next_state;
- reg data_out, data_out_returnl, data_out_return2;
- always @(current_state or data_in)
- case (current_state)
- 3'b000: case (data_in)
- 3'b000: begin
- next_state <= 3'b000;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b001: begin
- next_state <= 3'b001;
- data_out <= 1'bO;
- data_out_return 1 <= 1'bO;
- data_out_retum2 <= 1'bO;
- end
- 3'b010: begin
- next_state <= 3'b010;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b011: begin
- next_state <= 3'bl01;
- data_out <= 1'bO;
- data_out_return 1 <= 1'bO;
- data_out_retum2 <= 1'bO;
- end
- 3'bl00: begin
- next_state <= 3'bOOO;
- data_out <= 1'bl;
- data_out_retum1 <= 1'bO;
- data_out_retum2 <= 1'bl;
- end
- endcase
- 3'b001: case (data_in)
- 3'b000: begin
- next_state <= 3'b001;
- data_out <= 1'b0;
- data_out_retum1 <= 1'b0;
- data_out_retum2 <= 1'b0;
- end
- 3'b001: begin
- next_state <= 3'b010;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0:
- data_out_return2 <= 1'b0;
- end
- 3'b010: begin
- nexl_state <= 3'b011;
- data_out <= 1'b0;
- data_oul_return1 <= 1'b0;
- data_out_return2 <= 1'b0:
- end
- 3'b011: begin
- next_state <= 3'b110;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0:
- end
- endcase
- 3'b010: case (daia_in)
- 3'b000: begin
- next_state <= 3'b010;
- data_out <= 1'b0;
- data_out_returnl <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'bOO1: begin
- next_state <= 3'b011;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_oul_return2 <= 1'b0;
- end
- 3'b010: begin
- next_state <= 3'b100;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b011: begin
- next_state <= 3'b111;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- endcase
- 3'bO11: case (data_in)
- 3'b000: begin
- next_state <= 3'b011;
- data_out <= 1'b0;
- data_out_retuml <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b001: begin
- next_state <= 3'b100;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b010: begin
- next_state <= 3'b101;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b011: begin
- next_state <= 3'b000;
- data_out <= 1'b1;
- data_out_returnl <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- endcase
- 3'blOO: case (data_in)
- 3'bOOO: begin
- next_state <= 3'b000;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 31)001: begin
- next_state <= 3'b101;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b010: begin
- next_state <= 3'b110;
- data_out <= 1'b0;
- data_oul_return1 <= 1'b0;
- data_out_retumrn2 <= 1'b0;
- end
- 3'b011: begin
- next_state <= 3'b000;
- data_out <= 1'b1;
- data_out_return1 <= 1'b1;
- data_out_return2 <= 1'b0;
- end
- endcase
- 3'b101: case (data_in)
- 3'bOOO: begin
- next_state <= 3'b101;
- data_out <= 1'b0;
- data_out_retuml <= 1'b0;
- data_out_retum2 <= 1'b0;
- end
- 3'bOO1: begin
- next_state <= 3'b110;
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- 3'b010: begin
- next_state v= 3'bl 11;
- data_out <= 1'bO;
- data_out_retum1 <= 1'bO;
- data_out_retum2 <= 1'bO;
- end
- 3'bO11: begin
- next_state <= 3'b000;
- data_out <= 1'b1;
- data_out_return1 <= 1'b0;
- data_out_return2 <= 1'b1;
- end
- endcase
- 3'b110: case (data_in)
- 3'b000: begin
- next_state <= 3'b110:
- data_out <= 1'b0;
- data_out_return1 <= 1'b0;
- data_out_relurn2 <= 1'b0:
- end
- 3'b001: begin
- next_state <= 3'b111;
- data_out <= 1'b0;
- data_out_relurnl <= 1'bO:
- data_out_return2 <= 1'bO;
- end
- 3'b010: begin
- next_state <= 3'bOOO;
- data_out <= 1'b1;
- data_out_return1 <= 1'bO;
- data_out_return2 <= 1'bO;
- end
- endcase
- 3'b111: case (data_in)
- 3'bOOO: begin
- next_state <= 3'b111;
- data_out <= 1'b0;
- data_oul_return 1 <= 1'b0;
- data_out_retum2 <= 1'b0;
- end
- 3'bOO1: begin
- next_state <= 3'b000;
- data_out <= 1'b1;
- data_out_retum 1 <= 1'b0;
- data_out_return2 <= 1'b0;
- end
- endcase
- endcase
- always @(posedge clk or rst_n)
- if(!rst_n)
- current_state <= 3'bOOO;
- else
- current_state <= next_state;
- endmodule
- module seqdet (D_out, D_in, rst_n, clk);
- parameter IDLE = 3'd0, A = 3'd1,B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5;
- output D_out;
- input D_in, rst_n, clk;
- reg [2:0] state, next_state;
- wire D_out;
- assign D_out = (state == E)? 1:0;
- always @(state or D_in)
- case (state)
- IDLE : if(D_in) next_state = A;
- else next_state = IDLE;
- A : if(D_in) next_state = B;
- else next_state = IDLE;
- B : if(D_in) next_state = B;
- else next_state = C;
- C : if (D_in) next_state = D;
- else next_state = IDLE;
- D : if (D_in) next_state = B;
- else next_state = E;
- E : if (D_in) next_state = IDLE;
- else next_state = A;
- default: next_state = IDLE;
- endcase
- always @(posedge clk)
- state <= next_state;
- endmodule
$display("<format_specifiers>“, <signal1, signa!2, …,signaln>);
$write("<format_specifiers>", <signal 1, signal2,…,signaln>);
- module cntl0(clk, rst, ena, q, cout);
- input clk, rst, ena;
- output[3:0] q;
- output cout;
- reg[3:0] q;
- always @ (posedge clk or posedge rst)
- begin
- if(rst)q = 4'b0000;
- else if(ena)
- begin
- if(q<9)q = q+1;
- else q = 0;
- end
- end
- assign cout = q[3]&q[0];
- endmodule
-
- module cnt10_tb;
- reg clk, rst, ena;
- wire [3:0] q;
- wire cout;
- cnt_10 U1(clk, rst, ena, q, cout); //模块实例化
- always #50 elk = ~clk; //时钟信号产生
- initial
- begin
- clk = 0; rst = 0; ena = 1; //控制信号产生
- #1200 rst= 1;
- #120 rst = 0;
- #2000 ena = 0;
- #200 ena = 1;
- #20000 $finish;
- end
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。