verilog 中forever always_systemverilog中的基本变量类型

今天来看看systemverilog的变量类型。systemverilog的变量类型有2值和4值两种类型。4值是z(高阻态,我们常说是三态门中的高阻态是干什么用的呢?是用来实现让电线实现断开的,实际上就是通过门来控制一条线中接个很大的电阻来让这个线就想中间断了一样,这样这根线就不会影响其它电路了),x,0,1。 2值就是0和1。

(一)4值变量有4种,wire,reg,logic,integer。

首先咱们来看一看4值变量中最常见的wire和reg,关于他们俩有一个很常见的问题,就是为什么过程赋值(就是always块)中用reg,并且要用非阻塞赋值(<=,后面都写nonblocking赋值了,方便一点)。而连续赋值(就是assign语句,blocking赋值)中就要用阻塞赋值(=)。

实际上这也是承接了昨天的话题,因为要真正了解这件事情要追究到昨天所说的软件实现仿真所划分的active区和NBA区上。

首先assign语句对wire赋值,就相当于在模块里实现电线的连线,这是个一步到位的事情,所以我们用blocking,这样的话软件在执行的时候就是直接在active区里一步到位的。

而reg,实际上是一个flipflop,这玩意的值是能变的,对一个能变的东西,我们想,如果我们还是让他只在active区里一步到位,那么会有一个很大的问题,就是如果同时有俩always语句对它下命令,一个让它把值直接给另外一个数据a,一个让它取反后把值给另外一个数据b,那它在执行的时候会怎么办呢,谁的指令先来,它就先执行哪个。这样的话对与a和b的值我们就不能确定了。为了解决这个问题,我们引入了NBA区。看过上一篇的就明白是怎么回事了,我们先让这个数在active区分别把原本值和取反的值都找个地方记录下来,然后在NBA分别将记录好的两个值赋值给a和b,这样就不会出错了。

下面直接上代码:

(1)nonblocking的例子:

module nonblocking(y1,y2,clk,rst);
	output y1,y2;
	input clk,rst;
	reg y1,y2;
	
	always@(posedge clk or posedge rst)
		if(rst) y1 = 0;
		else y1 <= y2;
	
	always@(posedge clk or posedge rst)
		if(rst) y2 = 1;
		else y2 <= y1;
endmodule 

testbench

`timescale 1ns/1ps

module nonblocking_tb();
wire y1,y2;
reg clk,rst;

parameter PERIOD = 10;

	nonblocking nonblocking_1(
	.y1(y1),
	.y2(y2),
	.clk(clk),
	.rst(rst)
	);

initial begin
 clk = 0;
 #1;
 forever
    #(PERIOD/2) clk = ~clk; 
end 

	initial
	begin
	    rst = 1;
	    #1 rst = 0;
	    #100;
	    $finish;
	end

	endmodule

结果

8beec2569d5d229fd8f196955371a79d.png

这样的结果是没什么问题。

(2)如果我们在always语句中强行要用blocking赋值呢?

module nonblocking(y1,y2,clk,rst);
	output y1,y2;
	input clk,rst;
	reg y1,y2;
	
	always@(posedge clk or posedge rst)
		if(rst) y1 = 0;
		else y1 = y2;
	
	always@(posedge clk or posedge rst)
		if(rst) y2 = 1;
		else y2 = y1;
endmodule 

testbench

`timescale 1ns/1ps

module nonblocking_tb();
wire y1,y2;
reg clk,rst;

parameter PERIOD = 10;

	nonblocking nonblocking_1(
	.y1(y1),
	.y2(y2),
	.clk(clk),
	.rst(rst)
	);

initial begin
 clk = 0;
 #1;
 forever
    #(PERIOD/2) clk = ~clk; 
end 

	initial
	begin
	    rst = 1;
	    #1 rst = 0;
	    #100;
	    $finish;
	end

	endmodule

结果

21338165d7ab717d77066a0f9a7c7f76.png

喏,出问题了吧,这是很好理解的。

在这里补充一个资料:

cea7c5616af59828e33d4c98d79e082c.png

0cfbb501885b365d9fa66c37d45055d3.png

(3)接下来是logic和integer

logic简单来说就是一个又能放在always中当reg,又能放在assign中当wire用的变量,是纯软件的,不可综合。并且它还有一个好处是用它来写module的时候,可以省点笔墨,不用像verilog中那样,在module后面的端口声明中说一遍方向,然后在模块里面再说一遍变量的类型是wire还是reg。例子以后写了再补。

integer就是一个在C的int基础上,添加了z和x两个状态的32位数字。

(二)2值函数

2值函数就灰常直观易懂了。没啥可说的,直接把代码放这看一眼就好。

module data_types(
);
//2值
bit       data_1bit; 
byte      data_8bit; 
shortint  data_16bit;
int       data_32bit;
longint   data_64bit;

shortreal shortreal_32bit;
real real_32bit;

bit       unsigned data_1bit_unsigned;
byte      unsigned data_8bit_unsigned;
shortint  unsigned data_16bit_unsigned;
int       unsigned data_32bit_unsigned;
longint   unsigned data_64bit_unsigned;

initial begin
//2值
   $display("2type data");
   data_1bit   = {8{4'b1111}};
   data_8bit   = {8{4'b1111}};
   data_16bit  = {8{4'b1111}};
   data_32bit  = {8{4'b1111}};
   data_64bit  = {8{4'b1111}};
   shortreal_32bit= {8{4'b1111}};//浮点数
   real_32bit= {8{4'b1111}};//双精度浮点数

   //显示位数
   $display("width");
   $display("data_1bit    = %b",data_1bit);
   $display("data_8bit    = %b",data_8bit);
   $display("data_16bit   = %b",data_16bit);
   $display("data_32bit   = %b",data_32bit);
   $display("data_64bit   = %b",data_64bit);
   $display("shortreal_32bit   = %b",shortreal_32bit);
   $display("real_32bit   = %b",real_32bit);
   //显示表达的数字
   $display("show figure");
   $display("data_1bit    = %d",data_1bit);
   $display("data_8bit    = %d",data_8bit);
   $display("data_8bit    = %0d",data_8bit);//%前面的0表示不要显示数字前面的空格
   $display("data_16bit   = %0d",data_16bit);
   $display("data_32bit   = %0d",data_32bit);
   $display("data_64bit   = %0d",data_64bit);
   $display("shortreal_32bit = %d",shortreal_32bit);
   $display("real_32bit = %d",real_32bit);
   $display("shortreal_32bit = %f",shortreal_32bit);
   $display("real_32bit = %f",real_32bit);

   data_1bit_unsigned  ={8{4'b1111}}; 
   data_8bit_unsigned  ={8{4'b1111}};
   data_16bit_unsigned ={8{4'b1111}};
   data_32bit_unsigned ={8{4'b1111}};
   data_64bit_unsigned ={8{4'b1111}};
   $display("data_1bit    = %0d",data_1bit_unsigned);
   $display("data_8bit    = %0d",data_8bit_unsigned );
   $display("data_16bit   = %0d",data_16bit_unsigned);
   $display("data_32bit   = %0d",data_32bit_unsigned);
   $display("data_64bit   = %0d",data_64bit_unsigned);

   //2	值函数如果赋zx这样的值,zx会赋为0
   data_8bit   = {8{4'bzx01}};
   $display("data_8bit    = %b",data_8bit);
   $display("data_8bit    = %d",data_8bit);

   
   
   #1 $finish;
end

endmodule

结果

fc0f29b585dc147d82c502484ada8ac3.png
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值