学习FPGA(三)使能端

前言

        刚开学有点忙,要写专利、写论文,抽空休息写个小模块,正好昆明理工大学数字电子技术实验A(2023级)开始了,用的Altera的FPGA,我也来掺和一脚。

        在数字电子技术中,74系列的中规模集成电路都有一个使能端EN,这个端口的作用是使芯片运作,名如其用处。FPGA工程师在设计时一定会为模块添加使能端(我猜的,错了也请工程师前辈指正),来控制模块的运作。

        昆明理工大学数字电子技术实验A的实验任务有三个,分别是:1.利用3个拨动开关模拟3位二进制,在DIG1数码管上显示二进制对应字符;2.利用3个拨动开关模拟3位二进制,在二进制对应数码管上显示二进制对应字符;3.设计6选1数据选择器。(对应字符、对应位置即专属参数——昆明理工大学电子技术实验类特色)

        这本和使能端的关联度不大,我只是想从简单的模块中加入使能端,并理解其用法。

一、设计

        首先分析一下这三个任务,综合起来看其实就是设计三个数据选择器:1.通过设计8位数据选择器,将专属参数中的参数通过DIG1数码管输出;2.通过设计8位数据选择器,将专属参数中的参数通过数码管的位选和段选输出;3.通过设计6位数据选择器,将专属参数中的参数通过数码管输出(当然也可以是其他输出形式)。所以可以明确任务:设计数据选择器

        在学习FPGA(二)中,我已经将数码管点亮的子模块封装起来了,这里将对其进行修改,修改内容包括:1.加入英文字符的数码管显示;2.加入使能端。

        在主模块中,完成的内容是拨动开关的选择。三个开关对应3位二进制,即8个数;两个开关对应2位二进制,即4个数。拿出两个拨动开关用于任务的切换,拿出三个开关用于数据选择。

二、实现

        首先编写(修改)点亮数码管的子模块,英文字符的点亮规则这里按照昆明理工大学发的对照表来设计,当然如果有其它对应的可以替换。

1.修改seglight.v

        由于需要加入使能端,原子模块中直接输出点亮电平将不再适用,转而需要一个中间寄存器,存放点亮电平,而输出的电平则需要使能端与点亮电平的共同作用。具体程序如下。segnum输入0-9即输出数码管段选0-9的8位二进制,65-90即输出ASCII码对应英文字符的数码管段选8位二进制。最底下判断使能端enable的高低电平确定输出值。none的高组态设置是为了保护输出后的外部电路。

module seglight(enable, seg, dig, segnum, dignum);

input enable;
output [7:0] seg;
output [5:0] dig;
input [8:0] segnum;
input [4:0] dignum;
reg [7:0] seg_temp;
reg [5:0] dig_temp;

localparam seg_none = 8'bzzzzzzzz;
localparam seg_0 = 8'b11111100;
localparam seg_1 = 8'b01100000;
localparam seg_2 = 8'b11011010;
localparam seg_3 = 8'b11110010;
localparam seg_4 = 8'b01100110;
localparam seg_5 = 8'b10110110;
localparam seg_6 = 8'b10111110;
localparam seg_7 = 8'b11100000;
localparam seg_8 = 8'b11111110;
localparam seg_9 = 8'b11110110;
localparam seg_A = 8'b11101110;
localparam seg_B = 8'b00111110;
localparam seg_C = 8'b10011100;
localparam seg_D = 8'b01111010;
localparam seg_E = 8'b10011110;
localparam seg_F = 8'b10001110;
localparam seg_G = 8'b10111100;
localparam seg_H = 8'b01101110;
localparam seg_I = 8'b00001000;
localparam seg_J = 8'b01111000;
localparam seg_K = 8'b01011110;
localparam seg_L = 8'b00011100;
localparam seg_M = 8'b10101010;
localparam seg_N = 8'b00101010;
localparam seg_O = 8'b11001110;
localparam seg_P = 8'b11001110;
localparam seg_Q = 8'b11100110;
localparam seg_R = 8'b00001010;
localparam seg_S = 8'b10100110;
localparam seg_T = 8'b00011110;
localparam seg_U = 8'b01111100;
localparam seg_V = 8'b01111110;
localparam seg_W = 8'b10111000;
localparam seg_X = 8'b01010110;
localparam seg_Y = 8'b01110110;
localparam seg_Z = 8'b10010010;
localparam dig_none = 6'bzzzzzz;
localparam dig_1 = 6'b111110;
localparam dig_2 = 6'b111101;
localparam dig_3 = 6'b111011;
localparam dig_4 = 6'b110111;
localparam dig_5 = 6'b101111;
localparam dig_6 = 6'b011111;

always @(*)
begin
	case(segnum)
		0: seg_temp <= seg_0;
		1: seg_temp <= seg_1;
		2: seg_temp <= seg_2;
		3: seg_temp <= seg_3;
		4: seg_temp <= seg_4;
		5: seg_temp <= seg_5;
		6: seg_temp <= seg_6;
		7: seg_temp <= seg_7;
		8: seg_temp <= seg_8;
		9: seg_temp <= seg_9;
		65:seg_temp <= seg_A;
		66:seg_temp <= seg_B;
		67:seg_temp <= seg_C;
		68:seg_temp <= seg_D;
		69:seg_temp <= seg_E;
		70:seg_temp <= seg_F;
		71:seg_temp <= seg_G;
		72:seg_temp <= seg_H;
		73:seg_temp <= seg_I;
		74:seg_temp <= seg_J;
		75:seg_temp <= seg_K;
		76:seg_temp <= seg_L;
		77:seg_temp <= seg_M;
		78:seg_temp <= seg_N;
		79:seg_temp <= seg_O;
		80:seg_temp <= seg_P;
		81:seg_temp <= seg_Q;
		82:seg_temp <= seg_R;
		83:seg_temp <= seg_S;
		84:seg_temp <= seg_T;
		85:seg_temp <= seg_U;
		86:seg_temp <= seg_V;
		87:seg_temp <= seg_W;
		88:seg_temp <= seg_X;
		89:seg_temp <= seg_Y;
		90:seg_temp <= seg_Z;
		default:seg_temp <= seg_none;
	endcase
	
	case(dignum)
		1:dig_temp <= dig_1;
		2:dig_temp <= dig_2;
		3:dig_temp <= dig_3;
		4:dig_temp <= dig_4;
		5:dig_temp <= dig_5;
		6:dig_temp <= dig_6;
		default:dig_temp <= dig_none;
	endcase
end

assign seg = enable ? seg_temp : seg_none;
assign dig = enable ? dig_temp : dig_none;

endmodule

2.设计数据选择器assignment.v

        接下来是数据选择器。首先通过sw拨动开关的变动启动always块的内容(利用case设计的选择)。根据sw的末三位确认选择地址,可以根据专属参数修改case块内的segnum和dignum。比如拨动开关为000时,专属参数为‘A’第二个数码管输出,segnum就应该为65,dignum就应该为2;拨动开关为001时,专属参数为‘C’第四个数码管输出,segnum就应该为67,dignum就应该为4……。具体代码如下(根据专属参数修改case块中的每个segnum和dignum)。

module assignment(sw, dig, seg, enable);

input enable;
input [7:0] sw;
output [7:0] seg;
output [5:0] dig;
reg [8:0] segnum;
reg [4:0] dignum;
wire [7:0] seg_temp;
wire [7:0] dig_temp;

seglight seglight_1(
	.enable(enable),
	.seg(seg_temp),
	.dig(dig_temp),
	.segnum(segnum),
	.dignum(dignum)
);

assign seg = enable ? seg_temp : 8'bzzzzzzzz;
assign dig = enable ? dig_temp : 6'bzzzzzz;

always @(sw)
begin
	case(sw[2:0])
		0:
		begin
			segnum <= 65;
			dignum <= 2;
		end
		1:
		begin
			segnum <= 67;
			dignum <= 4;
		end
		2:
		begin
			segnum <= 1;
			dignum <= 6;
		end
		3:
		begin
			segnum <= 0;
			dignum <= 1;
		end
		4:
		begin
			segnum <= 8;
			dignum <= 3;
		end
		5:
		begin
			segnum <= 0;
			dignum <= 5;
		end
		6:
		begin
			segnum <= 9;
			dignum <= 2;
		end
		7:
		begin
			segnum <= 90;
			dignum <= 4;
		end
	endcase
end

endmodule

3.扩展数据选择器assignment_n.v

        将上述assignment模块复制出两个副本,用作三个不同任务,并修改需要显示的参数,在进行下一步主模块的编写。

4.编写主模块assignment2.v

        主模块中,需要实例化上一步完成的三个任务的子模块。由于分三个任务,这里将拨动开关的至高两位作为任务的切换,分别控制对应子模块的使能端。由于使能端失效时,子模块输出的seg和dig是高组态,因此不会影响使能端生效的子模块。具体代码如下。这里引入了使能端wire连线assignment_en,分段控制子模块的运行。

module assignment2(sw, dig, seg, enable, led, key);

input enable;
input [7:0] sw;
output [7:0] seg;
output [5:0] dig;
output [15:0] led;
input [7:0] key;
wire [3:0] assignment_en;

assign assignment_en[1] = sw[6] & sw[7];
assign assignment_en[2] = (sw[6] ^ sw[7]) & (~sw[6]);
assign assignment_en[3] = (sw[6] ^ sw[7]) & (~sw[7]);

assignment_2_1 assignment_1(
	.sw(sw),
	.dig(dig),
	.seg(seg),
	.enable(assignment_en[1])
);

assignment_2_2 assignment_2(
	.sw(sw),
	.dig(dig),
	.seg(seg),
	.enable(assignment_en[2])
);

assignment_2_3 assignment_3(
	.sw(sw),
	.dig(dig),
	.seg(seg),
	.enable(assignment_en[3])
);

endmodule

三、总结

        使能端的作用是控制芯片(子模块)的工作状态。在本次实例中,通过对实例化的子模块上加入使能端,将三个任务合并成了一个模块,提高了运行效率(昆工的小伙伴在验收时记得向老师解释这一段)。

        在将要封装的子模块中加上使能端时,也要注意其输出状态,防止输出到同一总线又没做好信号的侦听,导致信号扰动。我的理解是使能端控制运行,则输出特定内容;使能端控制禁用,则输出高组态(输出连总线)或保持安全状态(输出不接总线)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值