当前位置:   article > 正文

Verilog学习之路(4)— Verilog HDL的程序设计语句_用持续赋值语句描述一个4选1数据选择器

用持续赋值语句描述一个4选1数据选择器

Verilog HDL的程序设计语句

一、连续赋值语句

连续赋值语句通常用来描述组合逻辑电路,连续赋值的目标类型主要是标量线网和向量线网两种,标量线网如“wire a,b;”,向量线网如“wire [3:0] a,b”。连续赋值语句还可分为显示赋值语句和隐式连续赋值语句。
如下所示为显示连续赋值语句:

	wire a,b,c;
	assign c = a & b;
  • 1
  • 2

如下所示为隐式连续赋值语句:

	wire a,b;
	wire c = a & b;
  • 1
  • 2

如上所示,我们可以看到,显示连续赋值语句需要先类型声明(如wire),然后使用assign关键字进行描述,而隐式赋值语句则是在声明的时候即进行赋值描述。需要知道的是,连续赋值语句只能用来对连线型变量进行驱动,而不能对寄存器型变量进行赋值。

二、过程语句

1、initial过程语句

initial过程块在进行仿真时从仿真0时刻开始执行,整个initial过程块在执行完一次后就被挂起不再执行,如果模块中存在多个initial过程块,则每个initial过程块都是同时从0时刻开始并行执行的。initial过程语句通常用于仿真模块中对激励向量的描述,或用于给寄存器变量赋初值。
initial语句块不可被综合为实际电路。
如下所示为一个initial语句块对a,b,c赋值

module initial_tb1;
	reg a,b,c;
	
	initial begin
		a = 0; b = 1; c = 0;
		#100 a = 1; b = 0;
		#100 a = 0; c = 1;
		#100 b = 1; c = 0;
		#200;
	end
	
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

使用仿真工具查看波形可得如下所示
在这里插入图片描述

2、always过程语句

always语句块的触发由其后面的敏感事件列表决定,只要满足其敏感事件就执行该always过程块。always过程块的语法格式为

always@(<敏感事件列表>)
	语句块;
  • 1
  • 2

敏感事件列表可以如下所示

	@(a)									// 当信号a的值发生改变时
	@(a or b)								// 当信号a或信号b的值发生改变时
	@(posedge clock)						// 当clock的上升沿到来时
	@(negedge clock)						// 当clock的下降沿到来时
	@(posedge clk or negedge reset)			// 当clk的上升沿到来或reset的下降沿到来时
  • 1
  • 2
  • 3
  • 4
  • 5

always过程语句既可以描述时许逻辑电路,也可以描述组合逻辑电路,当我们使用不同的敏感事件列表时,会产生不同的电路形式,其设计要求如下:

  1. 描述组合逻辑电路时,需要把全部的输入信号列入敏感事件列表;
  2. 描述时许逻辑电路时,需要把时钟信号和部分输入信号列入敏感事件列表。

如下为一个典型的组合逻辑电路,4选1多路数据选择器,

module mux4_1(out, in0, in1, in2, in3, sel);
	output out;
	input in0,in1,in2,in3;
	input [1:0] sel;
	reg out;				// 过程块中被赋值信号需要定义为reg类型
	always@(in0 or in1 or in2 or in3 or sel) begin
		case(sel)
			2'b00:	out = in0;
			2'b01:	out = in1;
			2'b10:  out = in2;
			2'b11:	out = in3;
			default:out = 1'bx;
		endcase
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

经过综合后得到的电路图如下所示
在这里插入图片描述
如下是一个8位同步置数、同步清零计数器的代码,是一个典型的时序逻辑电路,

module counter(out, data, load, rst, clk);
	output out;
	input [7:0] data;
	input load, clk, rst;
	reg [7:0] out;				// 过程块中被赋值信号需要定义为reg类型
	always@(posedge clk) begin
		if(!rst)
			out = 8'h00;
		else if(load)
			out = data;
		else
			out = out + 1;
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

经过综合后得到的电路图如下所示
在这里插入图片描述

我们在敏感信号列表中加入rst信号后就可以变成异步复位的计数器,

module counter(out, data, load, rst, clk);
	output out;
	input [7:0] data;
	input load, clk, rst;
	reg [7:0] out;				// 过程块中被赋值信号需要定义为reg类型
	always@(posedge clk or negedge rst) begin
		if(!rst)
			out = 8'h00;
		else if(load)
			out = data;
		else
			out = out + 1;
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

经过综合后得到的电路图如下所示
在这里插入图片描述

三、过程赋值语句

过程赋值语句有阻塞赋值和非阻塞赋值语句两种。

1、阻塞赋值语句

阻塞赋值语句的操作符为“=”,其语法格式为

	变量 = 表达式;
  • 1

例如:

	b = a;
  • 1

当一个语句块中有多条阻塞赋值语句时,如果前面的赋值语句没有完成,则后面的语句就不能被执行,由此称为阻塞赋值方式。如下所示为使用阻塞赋值描述的电路

module block(din, clk, out1, out2);
	input din, clk;
	output out1, out2;
	reg out1, out2;
	always@(posedge clk) begin
		out1 = din;
		out2 = out1;
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

经过综合后得到的电路图如下所示
在这里插入图片描述

2、非阻塞赋值

非阻塞赋值语句的操作符为“<=”,其语法格式为

	变量 <= 表达式;
  • 1

例如:

	b <= a;
  • 1

如果在一个语句块中有多条非阻塞赋值语句,则后面语句的执行不会受到前面语句的限制,因此称为非阻塞赋值方式。
我们将上面的代码修改为使用非阻塞赋值方式

module non_block(din, clk, out1, out2);
	input din, clk;
	output out1, out2;
	reg out1, out2;
	always@(posedge clk) begin
		out1 <= din;
		out2 <= out1;
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

经过综合后得到的电路图如下所示
在这里插入图片描述

四、条件分支语句

Verilog HDL的条件分支语句有两种: if语句和case语句。条件语句只能在initial和always语句引导的语句块中使用。

1、if语句

if语句有如下三种形式:
在这里插入图片描述
一般来说,if语句蕴含了优先级的特性,如下代码为使用if语句写的一个4选1多路数据选择器,

module mux4_1(out, in0, in1, in2, in3, sel);
	output out;
	input in0,in1,in2,in3;
	input [1:0] sel;
	reg out;				// 过程块中被赋值信号需要定义为reg类型
	always@(in0 or in1 or in2 or in3 or sel) begin
		if(sel == 2'b00) out = in0;
		else if(sel == 2'b01) out = in1;
		else if(sel == 2'b10) out = in2;
		else if(sel == 2'b11) out = in3;
		else out = 1'bx;
		endcase
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

经过综合后得到的电路图如下所示, 可以看到,in0拥有最高的优先级。
在这里插入图片描述

2、case语句

if语句只有两个分支,而case语句可以有多个分支,且比if-else语句更为方便 和直观。case语句的真值表如下所示
在这里插入图片描述
另外还有casez和casex语句,其真值表如下所示
在这里插入图片描述
在使用case语句时,需要包含所有状态,如果没有包含完全,那么必须以缺省项写出,否则将产生锁存器,如下代码描述的电路即会产生锁存器

module latch_case(a, b, sel, out);
	input a,b;
	input [1:0] sel;
	output reg out;
	always@(a, b, sel) begin
		case(sel)
			2'b00: out = a;
			2'b11: out = b;
		endcase
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

经过综合后得到的电路图如下所示,
在这里插入图片描述
我们将缺省项加上之后:

module non_latch_case(a, b, sel, out);
	input a,b;
	input [1:0] sel;
	output reg out;
	always@(a, b, sel) begin
		case(sel)
			2'b00: out = a;
			2'b11: out = b;
			default: out = 1'b0;
		endcase
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

经过综合后得到的电路图如下所示,
在这里插入图片描述

五、循环语句

Verilog HDL中规定了四种循环语句,分别是foreverrepeatwhilefor语句,其多用于测试仿真程序的设计,foreverrepeatwhile语句都是不可综合成电路的,但for语句在某些时候是可综合的。如下所示,使用for语句实现一个8位的移位寄存器。

module shift_regist(q, d, rst, clk);
	output [7:0] q;
	input d,rst,clk;
	reg [7:0] q;
	integer i;
	always@(posedge clk) begin
		if(!rst)
			q <= 8'b0000_0000;
		else begin
			for(i=7; i>0; i=i-1)
				q[i] <= q[i-1];
			q[0] <= d;
		end
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

其综合后的电路图如下所示
在这里插入图片描述
若不使用for语句实现一个8位的移位寄存器可编写如下代码 ,其和使用for语句编写的代码是一致的;

module shift_regist(q, d, rst, clk);
	output [7:0] q;
	input d,rst,clk;
	reg [7:0] q;
	always@(posedge clk) begin
		if(!rst)
			q <= 8'b0000_0000;
		else 
			q <= {q[6:0], d};
	end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

六、附录

上一篇:Verilog学习之路(3)— Verilog HDL的基础知识
下一篇:Verilog学习之路(5)— Verilog HDL的结构描述方式

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

闽ICP备14008679号