//元件例化
//参数定义关键词parameter和localparam
//移位操作符号
<<左移 >>右移 补零
>>> <<< 有符号数移位,左移补零,右移考虑符号位第一位
****************************************************************************************
时序电路设计
1)边沿触发和电平触发不能混合(敏感信号表中posedge表示上升沿,negedge表示下降沿,电平触发不需要加这两个)
(2)边沿触发只在敏感信号表中出现,不在过程中出现
(3)异步在敏感信号表中的边沿触发表示,同时出现在过程中
(4)同步信号只出现在过程中,不出现在敏感信号表
//深入认识阻塞赋值和非阻塞赋值,非阻塞赋值每个赋值都会产生锁存器
=阻塞式赋值
目标变量名=驱动表达式;
立即得到值
1)阻塞其他语句的执行
2)赋值
3)更新目标变量,允许对本过程中其他语句的执行
三个步骤一次完成
非阻塞式赋值<=
同时在end得到值
中间使用的是之前的值
体现了并行性
综合结果相同
<=和<的使用原则
- 原则1: 时序电路建模时,用非阻塞赋值。
- 原则2:锁存器电路建模时,用非阻塞赋值。
- 原则3:用always块建立组合逻辑模型时,用阻塞赋值。
- 原则4:在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
- 原则5:在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
- 原则6:不要在一个以上的always块中为同一个变量赋值。
<=每一个被赋值的变量都会生成一个锁存器
多个=不会
//指定延时的阻塞式赋值
//
不完整条件语句与时序电路的关系:
组合电路必须是完整条件语句(if或者case语句完整生成电路无锁存器,否则会在不存在的条件产生锁存器保持)
利用不完整条件语句产生时序电路
//流水线优化
能够提高时钟的频率,使得每个结果所用的时间变短。。将一个延时长的组合电路设计成若干个延时短的电路
//状态机
module machine1(clk,x,z,reset);
parameter s0=0,s1=1,s2=2,s3=3;
reg[1:0] c_state,n_state;
input clk,x,reset;
output z;
reg z;
时序部分一定有
a[email protected](posedge clk ,negedge reset)
if(!reset) c_state<=s0;
else c_state<=n_state;
主控组合部分如下
case (c_state)
s0:begin if(x)n_state=s1;
else n_state=s0; z=0; end
s1:begin if(x)n_state=s2;
else n_state=s0; z=0; end
s2:begin if(x)n_state=s2;
else n_state=s3; z=0; end
s3:begin if(x)n_state=s1;
else n_state=s0; z=1;end
default: begin n_state=s0;z=0;end
endcase endmodule
Mealy状态机:输出不仅取决于当前状态,还和输入有关;
Moore状态机:输出仅仅与当前状态有关;
//13章
A = 'b0110;
^A的结果:
各位相互异或
initial块从仿真0时刻开始执行,在整个仿真过程中只执行一次。如果一个模块中包括了若干个initial块,则这些initial块从仿真0时刻开始并发执行,且每个块的执行是各自独立的。只被执行一次一个,模块可以有多个,所有的在一开始启动,不可综合。
功能:网线或寄存器类型的初始化
单次激励信号的发生
`timescale 1ns/100ps
`timescale 1ns/100ps
module test;
reg A,B,C;
initial
begin
A=0;B=1;C=0;
#50 A=1;B=0;
#50 A=0;C=1;
#50 B=1;
#50 B=0;C=0;
#50 $finish();
end endmodule
产生激励信号
*********************************************************************************
case语句
case考虑所有值的匹配。0 1 x z
casez 不考虑z位的匹配
casex 不考虑z 、x 位的匹配
//任何变量有4种逻辑状态
0 1 Z高阻态 X不确定
//条件赋值语句
//if()else()
//for语句
//repeat循环语句
// `define 宏名(标志符) 宏内容(字符串)
例如:
`define S A+B+C+D
assign DOUT=`S+E;
assign DOUT=A+B+C+D+E;
产生时钟信号
//包含语句`include
编译预处理
如果文件里面有`define 宏名,则源文件存在语句块1,则就有语句块2
//
module taskDemo(s,d,c1,d1,c2,d2);
input s;input[3:0] c1,d1,c2,d2;
output[3:0]d;
reg[3:0] out1,out2;
task CMP;
input[3:0] A,B;output[3:0]Dout;
begin if(A>B)Dout=A;
else Dout=B;
end
endtask
[email protected](*)begin
CMP(c1,d1,out1);
CMP(c2,d2,out2);
end
assign d=s?out1:out2;
endmodule
使用任务应注意:
- 任务使用顺序语句
- 定义不能放在过程结构中
- 调用在过程结构中
- 调用输入输出要与定义对应。
- 只能描述组合电路
6.任务可以包含时序控制,即时延控制
7.任务也能调用其它任务和函数
module CN(a,out);
input[3:0] a;output[2:0] out;
function[2:0] GP;
input[3:0]M;
reg[2:0]CNT,N;
begin CNT=0;
for(N=0;N<=3;N=N+1)
if(M[N]==1)CNT=CNT+1;
GP=CNT;
end
endfunction
assign out=(~|a)?0:GP(a);endmodule
里面隐含了一个函数名相同的变量,用于返回值,GP
函数定义应注意:
1.函数与任务的不同之处是函数只能返回一个值
2.函数不能包含任何时延或时序控制(必须立即执行)
3.函数定义只能放在模块中,不能放在过程结构中
4.函数内部可以调用函数,不能调用任务
5.过程语句和连续赋值语句中都可以调用函数
6.函数调用不能作为一个语句单独出现。
//display(“带格式字符串”,参数1,参数2,…);输出显示相当于C语言的printf
// fork join 并行
fork
#30 a=1;
#10 b=1;
join