4.2 initial 结构和 always 结构

引言部分

1.行为级建模的四种结构:

  • (1)initial 结构
  • (2)always 结构
  • (3)task 结构
  • (4)function 结构

2.initial 结构和 always 结构特点

  • 一个程序模块可以有多个 initial 和 always 过程块。
  • 一个 module 里的所有 initial结构 和 always结构,在仿真的一开始同时执行
  • initial 模块只执行一次always 模块的触发条件只要满足,就运行一次,直到仿真结束。
  • initial 结构和 always 结构都不支持嵌套使用,即 initial 结构中不能再出现 initial 结构。

一、 initial 结构

1. 语句格式

initial a=1; //仅包含一条语句
initial  //包含多条语句时
  begin
    语句 1;
    语句 2;
  end

2. initial 结构用途和用法

(1)initial 结构的主要功能就是 进行初始化,进行信号和变量初始化的常用形式。
(2)由其用途可推断其用法,initial 结构仅在仿真开始的时候被激活一次,然后该结构中所有语句执行一次,执行结束后不再执行

3. 举例说明

(1)对存储器变量赋初值

initial begin
  areg=0; //初始化寄存器areg
  for( index = 0; index < size; index++ )
    memory[index] = 0;   //初始化一个memory
end

注意:在仿真一开始就对各变量进行初始化,这个初始化过程不需要任何仿真时间,即在 0 ns 时间内,便可完成存储器的初始化工作。

(2)用于测试文件,生成激励波形。

//产生激励
initial begin
      a=0; b=0;
  #15 a=0; b=1;
  #15 a=1; b=0;
  #15 a=1; b=1;
  #15 a=0; b=0;
end
//产生时钟信号
initial clk = 1'b1;
always#(`clock_period/2) Clk = ~Clk;
//产生 Cin激励信号 和 Rst_n复位信号
	initial begin
		Rst_n = 0; //首先系统处于复位状态
		Cin = 1'b0;
		#(`clock_period*200); //延时200个系统时钟周期
		Rst_n = 1'b1; //系统开始运行
		#(`clock_period*20);
		
		repeat(30) begin //重复执行30次。1个周期高电平,5个周期低电平。
			Cin = 1'b1;
			#`clock_period;
			Cin = 1'b0;
			#(`clock_period*5);		
		end
		
		#(`clock_period*20);
		$stop;
	
	end

二、 always 结构

1.语句结构

always <时序控制方式> 执行语句

2.特点

可以执行多次,在仿真的过程中是时刻活动的。

3. 三种控制方式

  • a. 基于延迟的控制
  • b. 基于事件的控制
  • c. 基于电平敏感的控制

需要控制方式的原因:

always 结构时刻活动,如果没有控制方式的参与,此结构中的语句可能会一直执行并发生死锁,或者编程数据流级的语句。举个栗子:

always a=~a;  //因为没有控制,a会时刻把自己取反信号赋值给自己,生成死循环。
always sum=a+b; // 不如替换成:assign sum=a+b;

(1) 基于延迟的控制

  • always #5 a=~a; //每隔五个时间单位,把a取反信号赋给自己。
    时钟信号的生成
// 时钟信号的生成
initial clk=1;         //赋初值!!不能忘
always #10 clk=~clk;  //周期为20个时间单位的时钟。
  • 也可以添加多条语句,但一般少用。
//这样的信号也是一个时钟,但占空比不是50%,而是25%。
initial clk=0;
always 
begin
  #15 clk=1;
  #5 clk=0;
end  
  • 注意:语句前的延迟,是指延迟一定时间之后执行该语句,而不是该语句执行了多长时间。

(2)基于事件的控制

always @ (敏感事件表)

  • always 结构时刻观察敏感事件列表中的信号,等待敏感事件的出现,所有事件当中只要满足一个,就会执行本结构中的语句。

  • always@(a or b or c) // 只有a,b, c中有一个发生变化,就会执行always结构中的语句。
    always@(a,b,c)
    always@(*) // * 代表always结构中所有的输入信号

(3)基于电平敏感的控制

- 电平敏感:组合电路

- 边沿敏感:时序电路

eg.电平触发的 D 触发器

always@(clk or rst or d) begin
  if(rst) q <= 0;     // rst 为高电平时清零
  else if(clk)        // 否则当clk为高电平时,q输出d的值
    q <= d;
end

eg. 上升沿触发的同步清零 D 触发器

always@(posedge clk)begin //仅在 clk 上升沿来临时,才会执行always
  if(!rst) q <= 0;
  else q <= d;
end

eg. 上升沿触发的异步清零 D 触发器

always@(posedge clk or negedge rst) begin  //敏感列表包含了rst,rst每次从 1 变为 0 ,always 都会被执行,所以是异步清零。
  if(!rst) q <= 0;
  else q <= d;
end

注意:
1. 边沿触发的敏感列表不能使用 “*” 来省略,可以用“,”或者 or 。posedge 上升沿,negedge 下降沿。
2. 电平敏感和边沿敏感不要同时出现在敏感列表中。

posted @ 2022-04-23 22:03  烤冷面多加醋  阅读(920)  评论(0)    收藏  举报