数据选择器设计

数据选择器是指经过选择,把多个通道的数据传送到唯一的公共数据通道上去,实现数据选择功能的逻辑电路称为数据选择器。在多路数据传送过程中,能够根据需要将其中任意一路选出来的电路,叫做数据选择器,也称多路选择器或多路开关。在选择变量n控制下,从多路数据输入中某一路数据送至输出端。对于一个具有 2^n 个输入和 1 个输出的多路选择器,有 n 个选择变量。多路选择器也是 FPGA 内部的一个基本资源,主要用于内部信号的选通。简单的多路选择器还可以通过级联生成更大的多路选择器。

下边举例来说明一下数据选择器,不妨设选择器为2输入in1,in2,选择端为sel,输出out。
选择器的逻辑是这样的,如果sel=0,选择in2信号输出,即out=in2,如果sel=1,选择in1信号输出,sel=in1。而在数字电路当中,一个变量可以有两个状态0和1,所以两输入变量对应四种不同的结果,如果考虑选择端sel,则可以列出如下真值表所示。

selin1in2out
0000
0011
0100
0111
1000
1010
1101
1111

这样得到输出out的表达式为out=sel’&in2+sel&in1('表示反变量的意思)

根据上述真值表可以得到下边基本门电路组成的二选一数据选择器的电路图
在这里插入图片描述
但是在数字电路当中,我们不需要在门电路设计电路,只需要知道电路的逻辑功能,直接使用封装好的芯片即可,封装好的芯片就是把能实现一定功能的门电路封装起来,比如我们要实现的数据选择器,直接用比如说74HC153即可。并且verilog是在寄存器级的描述语言,只要你告诉它你要实现的功能,便会自动给出搭电路,我们下边的RTL视图就是软件实现我们描述的逻辑功能的电路。所以我们通常用下边的框图表示二选一数据选择器。

在这里插入图片描述

比如,常见的双二选一数据选择器的芯片如下图示

在这里插入图片描述

而在verilog语言里边,实现上述电路有三种方法,if语句和case语句,以及三目运算符实现。

下边分别给出三种不同实现方法的代码,以及对应的RTL视图,方便读者了解这三种实现方法的不同,尽管使用的语法不一样,但是最后电路实现的功能是一样的。所以大家在代码的实现上就有很多的选择,看到别人不同的写法也不要大惊小怪,我们要关注的是最后的功能,在不考虑资源使用的情况下只要功能满足要求,代码的灵活性可以随意控制。通过对比发现以上三种不同代码方式实现的 2 选 1 多路选择器对应综合出的 RTL 视图虽有所差别,但综合工具在布局布线和最后映射 FPGA 资源时会自动优化,使最终的功能和占用的逻辑资源都是相同的。

这里介绍2输入的数据选择器,对于输入个数更大的数据选择器,请读者类推。

下边给出三种实现方法和对应的RTL视图以及仿真波形(三种实现方式波形一致),读者可以挑其中一种实现方法即可。

如果不记得软件的操作和仿真设置可以点击下边链接查看。

软件的使用和仿真设置看这里

代码实现和仿真波形

一、if-else语句实现代码

module mux2_1(
	input wire in1,in2,//两个输入变量
	input wire sel,//数据选择端
	output reg out//输出信号端

);

	always @ (*)
		if(sel==1'b1)
			out=in1;
		else
			out=in2;
endmodule

RTL视图
在这里插入图片描述
二、case语句实现

module mux2_1(
	input wire in1,in2,//两个输入变量
	input wire sel,//数据选择端
	output reg out//输出信号端

);

always @ (*)
	case(sel)
		1'b0:out=in1;
		1'b1:out=in2;
		default:out=in1;
	endcase

endmodule

RTL视图

在这里插入图片描述
三、三目运算符实现

module mux2_1(
	input wire in1,in2,//两个输入变量
	input wire sel,//数据选择端
	output wire out//输出信号端

);

	assign out=(sel==1'b1)? in1:in2;
	
endmodule

RTL视图
在这里插入图片描述

三、仿真文件编写

`timescale 1ns/1ns

module tb_mux2_1();

	reg in1,in2,sel;
	wire out;

initial
begin//将变量赋初值为0
	in1<=1'b0;
	in2<=1'b0;
	sel<=1'b0;
end
//每个10ns 变量随机取值为0或者1,不用人为赋值
always #10 in1<={$random} % 2;
always #10 in2<={$random} % 2;
always #10 sel<={$random} % 2;

//下边的initial块的语句可以不要,只是方便波形的观察
initial begin
	$timeformat(-9,0,"ns",6);//设置显示的时间格式,此处表示的是(打印时间单位为纳秒,
//小数点后打印的小数位为 0 位,时间值
//后打印的字符串为“ns”,打印的最小数量字符为 6 个)
	$monitor("@time %t:in1=%b in2=%b sel=%b out=%b",$time,in1,in2,sel,out);
	//只要监测的变量(时间、in1, in2, sel, out)发生变化,就会打印出相应的信息
end

mux2_1 mux2_1_inst(//模块实例化
.in1(in1),
.in2(in2),
.sel(sel),
.out(out)

);
endmodule

这里使用了 $monitor系统函数来输出变量的值, 用法如下 $monitor(“%b+%b=%d”,a,b,c); //“%b+%b=%d” 格式控制,未指定时默认十进制
%h 或%H //以十六进制的形式输出
%d 或%D //以十进制的形式输出
%o 或%O //以八进制的形式输出
%b 或%B //以二进制的形式输出

$time 为时间函数,返回 64 位当前仿真时间; $random 用于产生随机函数,返回随机
数,{ $random} % n返回一个0到n-1的随机数。

系统函数的用法比较固定,如果不理解,也不影响输出的波形,直接方便读者观看结果而已

波形图
在这里插入图片描述

根据波形图sel的取值,看sel=1时,out是否等于in1,sel=0时,out是否等于in2,即可验证波形的正确性。

为了观看变量在不同时刻的值,可以选择Modelsim的”View“下”Transcript“,即可观看变量在不同时刻的值

在这里插入图片描述
比如550ns(下图第5行)时,sel=1,此时应该选择sel,所以out和in1输出一致,尽管in2=1,但是out选择的是in1
在这里插入图片描述

下节内容——3-8译码器

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐