Verilog HDL_基本概念

示例引入

//行为级HDL代码
// 整数乘法器
always @ (posedge multiply)
begin
	product <= a*b // 非阻塞赋值 相当于等号
end 
//RTL级HDL代码
input [4:1] a,b;  //位宽是4,位权从4到1   输入变量
output[4:1] count;  // 输出变量
output[16:1] product;
reg[4:1] count; // 寄存器变量
reg[4:1] product;
always @ (posedge clk)
begin
	if (multiply_en == 1) begin
		count <= 4;
		product <= 0;
	end
	if (count) begin
		if(b[count]) begin // b[count] == 1
			product <= (product << 1) + a;
		end
		else begin // b[count] == 0 
			product <= product << 1;
		end
		count <= count - 1;
	end
end
// 门电路级HDL代码
module UnsignedMultiply(clk,a,b,multiply_en,product);
	input clk,multiply_en;
	input[3:0] a,b;
	output[7:0] product;
	wire clk;
	wire un1_count5_axb_1;
	......
endmodule

模块的基本概念

选择器

请添加图片描述
实现上述元件(二选一数据选择器)的功能:

module mux2(out,a,b,sel); // module name(端口列表)  注意分号
	input a,b,sel; // 输入
	output out;  // 输出
	reg out; // 寄存器类型 always被赋值的对象需要为寄存器类型
	always @(a or b or sel) // 括号里为信号,在接收到这些信号时,进行之后的操作
		if (!sel) out = a;
		else out = b;
endmodule

请添加图片描述
由与门和非门和或门组成,sel=1,则nsel=0,此时选择b,sel=1,则nsel=1,此时选择a。

// `timescale 1ns/1ns 声明仿真时间单位
module mux2(out,a,b,sel);
	input a,b,sel;
	output out;
	wire nsel.sela.selb; //wire是连线型变量,为中间变量
	 //not,and,or 为元语,表示非门、与门、或门
	 //端口参数列表为:第一个是输出,其余全是输入
	not u1(nsel,sel); // not是一个声明,变成具体的电路还需要名称
	// not #1 u1(nsel,sel) 在进入门之前有一个仿真时间单位的延迟
	and u2(sela,a,nsel);
	and u3(selb,b,sel);
	or u4(out,sela,selb);
endmodule

全加器

行为级描述

module adder4(cout,sum,a,b,cin)
	input [3:0] a,b; //[3:0]是位宽表达式
	input cin;
	output cout;
	output [3:0] sum;
	assign {cout,sum} = a+b+cin
endmodule

4位全加器,根据两个4bit的加数a、b和进位输入cin计算sum和进位输出cout。

assign属于连续赋值语句,属于行为描述方式。

assign的变量需要声明位连线型(wire),一般而言,不给output额外声明reg形式,它就是连线型。

值得一提的是,全部程序是位于module和endmodule之间的。

比较器

module compare2(equal,a,b);
	input[1:0] a,b;
	output equal;
	assign equal = (a==b) ?1:0; //条件运算符
endmodule

Verilog和C语言的注释方式是一致的。

如果要将条件运算符表达式表示用if-else表示需要使用always @ (),因为Verilog中不允许表达式语句独立存在,除了条件表达式。

always语句中的变量需要声明位reg类型。

三态缓冲器

通过调用Verilog语言提供的原语库中三态驱动器元件bufif1实现,也可以自定义模块使用。

module trist2(sout,sin,ena);
	input sin,ena;
	output sout;
	mytri tri_inst(.out(sout),.in(sin),.en(ena));
	 // .表示被引用模块的端口,名称必须一致,()表示本模块中与之连接的端口
	 // 也可以直接写本模块中的模块,但需要顺序对上,不建议使用
endmodule

module mytri(out,in,en);
	input in,en;
	output out;
	assign out = en ? in : 1'bz; // 1‘bz表示1bit的数值
endmodule

综上所述,实现功能的方式有三种:

  1. 元语言;
  2. always;
  3. 过程块;

模块的测试

请添加图片描述

`include "mux2.v" //Verilog HDL默认扩展名 .v
module tstmux; //没有端口参数列表,这是测试向量的名称
reg ain,bin,sel_in;
reg clock;
wire outw; // 就是一根线,将输出信号引到被测模块

// 寄存器中的初始值是不确定的,因此要赋值
initial // 专门用来做变量初始化
begin
	ain = 0;
	bin = 0;
	sel_in = 0;
	clock = 0;
end

// 产生一个不断重复的,周期为100个单位时间的时钟信号
always #50 clock = ~clock;
always @ (posedge clock)
begin
	ain = {$random} % 2; //-32768~32767 随机数函数 ,目的是防止人为规定模式,导致测试覆盖范围不全
	#3 bin = $random % 2; // 取余
end

always @(posedge clock)
begin
	ain = {$random} % 2;
	#3 bin = $random % 2;
end

always #10000 sel_in = ! sel_in;

// 将上述信号传递给编辑的module
mux2 m(.out(outw),.a(ain),.b(bin),.sel(sel_in));
endmodule


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右边是我女神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值