HDLs是硬件描述语言(Hardware Description Languages)的简称
HDL有很多,目前主流的是Verilog HDL (Verify Logic)和VHDL(Very High Speed Integrated Circuit HDL)
然而我们依旧要从过时的语言AHDL(Altera HDL)学起
纵观AHDL
格式
AHDL文件的格式包括三个部分:
- Documentation:注释
- I/O定义,包括mode和type
- Mode:定义一个端口是输入/输出抑或两者兼备
- Type:定义bits的数量 - Functional description: 定义电路的逻辑
操作符
例子:或门
- SUBDESIGN:给这个电路模块命名
- 定义输入和输出以及双向端口,包含在括号里
- 在BEGIN和END中间描述逻辑
Buried nodes
电路中有一些点既不是输入也不是输出,这个点只在这个模块里好使,这些点被叫做Buried nodes
Buried 需要用variable来声明,如图:
上面变量中的NODE是一种类型,还有许多其他类型,比如DFF,JKFF等
AHDL vs Programming Language
AHDL中的描述是并发进行的,不像计算机编程语言逐行编译
Representing Data in AHDL
AHDL能够识别的字符包括:
- 26个字母的大小写
- 数字0-9
- 斜杠 “/”
- 下划线 “_”
书写字符的注意事项:
- 可以以数字开头
- 不可以是保留字(如END, BEGIN)
- 大小写不敏感
数字的表现
进制 | AHDL | 等价十进制 |
---|---|---|
二进制 | B"101" | 5 |
十六进制 | H"101" | 257 |
十进制 | 101 | 101 |
注意,VCC和GND是两个常数
Bit Array and Bit Vector
位数组或位向量可以被用来描述一个拥有多个数据位(Data Bit)的端口或节点
声明
声明一个名字,后面跟着数据范围,如下所示
p1 [7..0] :INPUT; --DEFINE AN 8-BIT INPUT PORT
上述代码声明了一个8-bit的输入端口
单独的bit可以被指定bit来访问,如p1[5]
赋值
将上文中声明的8-bit端口p1分配给一个名为temp的节点,代码如下:
VARIABLE temp[7..0]:NODE;
BEGIN
temp[]=p1[];
END
空的括号意味着所有数组中的bits都已经连接了
单个的bit也可以连接,如:
temp[0] = p1[0]
Operators
AHDL中许多的运算符都与C中的相同
Concatenation Operator
并置运算符可以通过在括号中放置节点名/组名,将节点(和其他组)组合到一个组中,代码如下:
g[3..0] = (a, b, c, d);
或
(a, b, c, d) = g[3..0];
这也可以被用来在一个语句中分配多个端口,如
(a, b) = B"10";
Truth Table in AHDL
在AHDL中,可以通过声明真值表来设计电路,这需要用到关键字“TABLE”
示例所用的真值表如下:
a | b | c | y |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 0 | 0 | 0 |
1 | 0 | 1 | 1 |
1 | 1 | 0 | 1 |
1 | 1 | 1 | 1 |
对应的代码如下所示:
SUBDESIGN TRUTH_TABLE
(
a,b,c :INPUT; --define inputs
y :OUTPUT; --define output
)
BEGIN
TABLE
(a,b,c) => y; --column headings
(0,0,0) => 0;
(0,0,1) => 0;
(0,1,0) => 0;
(0,1,1) => 1;
(1,0,0) => 0;
(1,0,1) => 1;
(1,1,0) => 1;
(1,1,1) => 1;
END TABLE;
END;
还有一种用到并置运算符的形式,代码如下:
SUBDESIGN TRUTH_TABLE
(
a,b,c :INPUT; --define inputs
y :OUTPUT; --define output
)
VARIALBLE in_bits[2..0] :NODE;
BEGIN
in_bits[] = (a,b,c) --concatenating
TABLE
in_bits[] => y; --column headings
b"000" => 0;
b"001" => 0;
b"010" => 0;
b"011" => 1;
b"100" => 0;
b"101" => 1;
b"110" => 1;
b"111" => 1;
END TABLE;
END;
Decision Control in AHDL
IF/THEN/ELSE
AHDL中的逻辑语句通常由 IF/THEN/ELSE组成
- IF/THEN 决定做还是不做
- IF/THEN/ELSE 决定做A还是做B
下方是一个使用IF,THEN,ELSE的例子:
SUBDESIGN IF_THEN_ELSE
(
digital_value(3..0) :INPUT; -- define inputs to block
z :OUTPUT; -- define block output
)
BEGIN
IF digital_value[] > 6 THEN
z = VCC; -- output a 1
ELSE z = GND; -- output a 0
END IF;
END;
注意AHDL中的IF必须在结尾加上ENDIF
CASE
CASE可以类比为C里面的SWITCH,一个CASE里可以设置不同的对应关系从而达到多个ELSE的效果
示例代码如下:
SUBDESIGN CASE
(
a,b,c :INPUT -- define input
s :OUTPUT -- define output
)
VARIABLE
status[2..0] :NODE;
BEGIN
status[] = (p,q,r); -- link input bits in order
CASE status[] IS
WHEN b"100" => s = GND;
WHEN b"101" => s = GND;
WHEN b"101" => s = GND;
WHEN OTHERS => s = VCC;
END CASE;
END;