本节通过例子介绍简单组合逻辑电路的描述方法。
例子1:通过按键控制LED的亮灭。
实现思路:通过模块的电路图看出,按键1接在FPGA芯片的pin 3。我们需要:
具体操作:
1、复制上节的工程目录,改名。
2、编辑top.v,在module的端口列表中增加button1:
module top
(
input wire button1,
output wire led0
);
3、编辑tangnano9k.cst,增加key1和引脚3的对应关系:
IO_LOC "button1" 3;
IO_PORT "button1" PULL_MODE=UP;
IO_LOC "led0" 10;
IO_PORT "led0" PULL_MODE=UP DRIVE=8;
4、编辑top.v,将原来的“assign led0 = 0;”修改为:
module top
(
input wire button1,
output wire led0
);
assign led0 = button1;
endmodule
5、烧写,观察
可以看到没按下button1时,led灭;按下时,led亮。
即:button1没按下时,pin3输入高电平;按下时,pin3输入低电平。
6、改为:button1松开亮、按下灭
思路:对button1接非门再接led0。
那么,非门怎么表示呢?试试c语言的求反符号:
assign led0 = ~button1;
例子2:通过两个按键的组合状态控制LED的亮灭。
思路:首先要增加按键端口,查电路图按键0接在引脚4;然后对两个按键进行组合运算。
同样的,试试c语言的位操作表示方式:与、或、异或符号(&、|、^)。
assign led0 = button1 | button0;
回顾数电课程中的存储芯片,连接地址总线的有若干个引脚:A0-An,连接数据总线的有若干个引脚:D0-Dn。它们的行为类似,对它们的声明和操作的语句相似。那么我们可以用Vector这个概念对它们同时进行声明和操作。
如果逐个列出来声明和操作不是不行,比如:
wire a0, a1, a2, a3;
assign a0=1;
assign a1=0;
assign a2=1;
assign a3=0;
用Vector的方式表示则是:
wire [3:0] a;
assign a=4'b1010;
注意:这种形式在Verilog里面称为Vector,不是数组,后面会介绍数组的形式。
这里引入两种新的表示方式:[MSB:LSB]和n'b。“wire [3:0] a;”声明变量a代表由4条线组成的线束,每条线可以分别用a[0]、a[1]、a[2]、a[3]表示。
“4'b1010”表示4比特的二进制整数常数,其中“4'”表示线束的宽度,其值为0b1010。要表达同样的值,还可以分别用十进制或十六进制表示为:“4'd10”或者“4'ha”。
再看一个例子:
wire [3:0] a, b, c;
assign a = 4'b1010;
assign b[0] = 1'b0;
assign b[3:1] = a[2:0];
assign c = {1'b1, b[0], a[3:2]};
“assign b[3:1] = a[2:0];”演示对线束中的一部分进行连接,“=”表示将两侧的线束中的线按次序分别连接。等同于:
assign b[3]=a[2];
assign b[2]=a[1];
assign b[1]=a[0];
“{1'b1, b[0], a[3:2]}”表示将若干条线或线束组合起来(大括号表示组合,逗号分割)。“assign c = {1'b1, b[0], a[3:2]};”等同于:
assign c[3]=1'b1;
assign c[2]=b[0];
assign c[1]=a[3];
assign c[0]=a[2];
描述多束相同比特数的线,可以用“数组”表示。例子:
wire [7:0] a[0:2];
表示声明3组8比特的线束:a[0]、a[1]、a[2]。
个人建议比特数目的声明用[MSB:0],数组元素个数的声明用[0:N-1]。虽然Verilog的规范是很灵活,还可以用负数。
多组位数相同(即线数相同)的线束之间的组合逻辑,同样用类同c语言的与、或、非、异或符号和小括号组成表达式进行表示即可。
线束中各条线的高低电平组成一个多位二进制数,可以被理解为有符号或无符号的整数或小数(定点小数或浮点小数)。
在Verilog中,可以用类同c语言的操作符号进行加减乘除。其中加法和减法可以只用组合逻辑电路表示。下面是无符号整数加法的演示:
module top
(
input wire [1:0] button,
output wire [5:0] led
);
assign led[1:0] = ~button;
assign led[3:2] = ~(button+2'b01);
assign led[5:4] = ~(button-2'b01);
endmodule
IO_LOC "led[5]" 16;
IO_PORT "led[5]" PULL_MODE=UP DRIVE=8;
IO_LOC "led[4]" 15;
IO_PORT "led[4]" PULL_MODE=UP DRIVE=8;
IO_LOC "led[3]" 14;
IO_PORT "led[3]" PULL_MODE=UP DRIVE=8;
IO_LOC "led[2]" 13;
IO_PORT "led[2]" PULL_MODE=UP DRIVE=8;
IO_LOC "led[1]" 11;
IO_PORT "led[1]" PULL_MODE=UP DRIVE=8;
IO_LOC "led[0]" 10;
IO_PORT "led[0]" PULL_MODE=UP DRIVE=8;
IO_LOC "button[1]" 3;
IO_PORT "button[1]" PULL_MODE=UP;
IO_LOC "button[0]" 4;
IO_PORT "button[0]" PULL_MODE=UP;
综合、烧写。自行分析两个按键按没按下时6个LED的状态。(注意:按键松开为1、LED低电平亮)
有符号整数的表示有一个关键字signed,以后再介绍。
在c语言的赋值语句中有“?”表达式,在Verilog中用同样的形式来表示二选一选择器。
assign y = select ? a : b;
表示当表达式为真时(即非0),y=a;为假时,y=b。
b可以继续用问号表达式来表示从而形成多路选择器:
assign y = select1 ? a :
select2 ? b :
select3 ? c : default;
在c语言中移位的符号是“<<”和“>>”,在Verilog中同样用这两个符号表示左移和右移。
在模块中试试这个例子:
assign led = (~button[1]) ? (~(6'h0c<<2)) :
(~button[0]) ? (~(6'h0c>>2)) : (~6'h0c);
等于:(button == 2'b01)
大于:(button > 2'b00)
小于:(button < 2'b10)
还有其它的大于等于、小于等于、不等于自己尝试。
另外还有多个比较表达式之间逻辑与、或、非的表示自己尝试。
上面的语句“(~button[1])”等同于“(button[1]==0)”。
本节简单介绍了如下Verilog关键字和概念:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。