Professional Documents
Culture Documents
3.5.1 AHDL 简介
一个 AHDL 逻辑设计至少必须包含一个分设计段 (Subdesign Section) 和一个逻辑设计段
(Logic Section),
其它段和语句是可选择的, AHDL 的设计文件是用 Max+PlusⅡ 软件的文本编辑器编写的
源程序(*.tdf)
下面介绍 AHDL 的一些语句。
( 1)常数叙述语 句
该语句可以用一个字符串代表数字、算数表达式
例:
CONSTANT UPPER_LIMIT = 130;
CONSTANT BAR = 1 + 2 DIV 3 + LOG2(256);
CONSTANT FOO = 1;
CONSTANT FOO_PLUS_ONE = FOO + 1;
(3)参数叙述语 句
该语句可以声明参数化巨功能模块和宏功能模块的一个或几个参数
114
太原理工大学 夏路易
例:
PARAMETERS
(
FILENAME = "myfile.mif", -- optional default value follows "=" sign
WIDTH,
AD_WIDTH = 8,
NUMWORDS = 2^AD_WIDTH
);
(4)函数描述语 句
共有 4 种形式的逻辑函数可以供用户调用,它们是:
Megafunction—具有复杂逻辑功能的巨功能模块,放在 mega_LPM 库中,可以供用户调用
Primitive—一些基本逻辑功能函数,可以直接调用
Macrofunction—具有高水平的逻辑宏功能模块,共有 300 多种,放在 max2lib 子目录中
State Machine—一种具有多个状态的时序电路,可以形成符号图形,用户可以调用
以上几种逻辑功能函数都可以以逻辑函数名和符号图形的方式被调用,在 AHDL 源文件
中调用时要首先进行声明,见如下例子。
1)参数化函 数:
FUNCTION lpm_add_sub (cin, dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0], add_sub)
WITH (LPM_WIDTH, LPM_REPRESENTATION, LPM_DIRECTION, ADDERTYPE,
ONE_INPUT_IS_CONSTANT)
RETURNS (result[LPM_WIDTH-1..0], cout, overflow);
该 函 数 名 为 lpm_add_sub , 输 入 端 口 为 cin, dataa[LPM_WIDTH-1..0], and
datab[LPM_WIDTH-1..0];
关键字 WITH 后是参数表,
关键字 RETURN 后是输出口 result[LPM_WIDTH-1..0], cout, and overflow
2)非参数化 函数 :
FUNCTION compare (a[3..0], b[3..0])
RETURNS (less, equal, greater);
该函数名为 compare,输入端口为 a3, a2, a1, a0, b3, b2, b1, and b0.
关键字 RETURN 后是输出口 less, equal, greater
3)状态机函 数:
当输入和输出是状态机时,应该按照如下例子定义函数,在返回结果语句中加 MACHINE
关键字
FUNCTION ss_def (clock, reset, count)
115
太原理工大学 夏路易
(6)断言语句
该语句可以检验表达式、参数、数据、计算函数有效性和端口的使用情况。
例:
ASSERT (WIDTH > 0)
REPORT "Width (%) must be a positive integer" WIDTH
SEVERITY ERROR
HELP_ID INTVALUE; -- for internal Altera use only
在 该 例 中 , WIDTH>0 是 断 言 条 件 , 若 此 条 件 不 满 足 , 将 显 示 REPORT 后 的 内 容 和
SEVERITY 后的错误等级。
(7)分设计段
分设计段声明输入、输出和双向口
例:
SUBDESIGN top
(
foo, bar, clk1, clk2 : INPUT = VCC;
a0, a1, a2, a3, a4 : OUTPUT;
b[7..0] : BIDIR;
)
端口类型可以是:
INPUT, OUTPUT, BIDIR, MACHINE INPUT, 或 MACHINE OUTPU
其中 MACHINE INPUT 或 MACHINE OUTPUT 口不能用于 TDF 的顶层,在端口类型说明
后可以加端口当前电平—VCC 或者是 GND。
(8)变量段
该段是声明和产生逻辑段中使用的变量的地方,如下是变量段的例子。
VARIABLE
116
太原理工大学 夏路易
a, b, c : NODE;
temp : halfadd;
ts_node : TRI_STATE_NODE;
IF DEVICE_FAMILY == "FLEX8000" GENERATE
8kadder : flex_adder;
d,e : NODE;
ELSE GENERATE
7kadder : pterm_adder;
f,g : NODE;
END GENERATE;
1)函数变量 声明例:
VARIABLE
comp : compare;
adder : lpm_add_sub WITH (LPM_WIDTH = 8);
该变量段声明 comp 为函数 compare 的引用变量,声明 adder 为函数 lpm_add_sub 的引用变
量,一旦声明完毕,就意味着:
变量 comp 就是如下端口的代表:
a[3..0], b[3..0] : INPUT; -- inputs to compare
less, equal, greater : OUTPUT; -- outputs of compare
而变量 adder 是如下端口的代表:
a[8..1], b[8..1] : INPUT; -- inputs of adder
sum[8..1] : OUTPUT; -- outputs of adder
也就是如下的引用变量可以使用在当前的设计文件中:
comp.a[], comp.b[], comp.less, comp.equal, comp.greater
adder.dataa[], adder.datab[], adder.result[]
2)节点变量 声明
AHDL 软件支持两种节点形式:NODE and TRI_STATE_NODE。
例:
SUBDESIGN node_ex
(
a, oe : INPUT;
b : OUTPUT;
c : BIDIR;
)
VARIABLE
117
太原理工大学 夏路易
b : NODE;
t : TRI_STATE_NODE;
BEGIN
b = a;
out = b % therefore out = a %
t = TRI(a, oe);
t = c; % t is bus of c and tri_stated a %
END;
如下的端口和功能模块能连接三态节点(TRI_STATE_NODE):
TRI 三态功能模块
输入端口(INPUT) 端口从高层向下
输出或双向口(OUTPUT, BIDIR)从低层向上
当前文件中的双向口(BIDIR)
当前文件中的三态节点 TRI_STATE_NODE
3)寄存器变 量声明
该声明用于声明寄存器:
D 型:DFF,DFFE,
T 型:TFF,TFFE
JK 型:JKFF,JKFFE,SRFF,SRFFE
琐存器:LATCH
例:
VARIABLE ff : TFF;
该变量一旦声明完毕,就可以使用如下变量:
ff.t, ff.clk,ff.clrn,ff.prn,ff.q
对于只有一个输出的功能模块,可以简化使用。
DFF 的功能说明为:
FUNCTION DFF(d, clk, clrn, prn) RETURNS (q);.
则对于如下的变量段,逻辑段的意思是 a.d = b.q;
VARIABLE
a, b : DFF;
BEGIN
a = b;
END;
4)状态机变量声明
118
太原理工大学 夏路易
例:
VARIABLE
ss : MACHINE
OF BITS (q1, q2, q3)
WITH STATES (
s1 = B"000",
s2 = B"010",
s3 = B"111");
该例的意思是:
状态机的名字是 ss ,状态位 q1, q2, 和 q3 是该机寄存器的输出,状态机的状态是 s1,s2, 和
s3, 并给出了当前状态值。
(9)逻辑段
在逻辑段中,说明设计文件的逻辑操作。
1)布尔方程
逻辑段中布尔方程用于表达节点之间的逻辑关系,该关系必须遵从逻辑规则。
例:
a[] = ((c[] & -B"001101") + e[6..1]) # (p, q, r, s, t, v);
表达式的左边可以是一个字符变量、端口和组,右边是布尔方程表达式。
2)布尔控制方 程
该控制方程用于建立状态机的时钟、复位和时钟使能信号,见下例:
ss.clk = clk1;
ss.reset = a & b;
ss.ena = clk1ena;
该控制方程的格式为<状态机名>.<端口名>,所以该例中状态机名是 ss,三个端口:时钟、复
位和使能。
3)CASE 语句
例:
CASE f[].q IS
WHEN H"00" =>
addr[] = 0;
s = a & b;
WHEN H"01" =>
count[].d = count[].q + 1;
WHEN H"02", H"03", H"04" =>
119
太原理工大学 夏路易
f[3..0].d = addr[4..1];
WHEN OTHERS =>
f[].d = f[].q;
END CASE;
3)缺省叙述语 句
该语句指定真值表中变量的缺省值,
例:
BEGIN
DEFAULTS
a = VCC;
END DEFAULTS;
IF y & z THEN
a = GND;
END IF;
END;
4) IF THEN 语句
例:
IF a[] == b[] THEN
c[8..1] = H "77";
addr[3..1] = f[3..1].q;
f[].d = addr[] + 1;
ELSIF g3 $ g4 THEN
f[].d = addr[];
ELSE
d = VCC;
END IF;
4)FOR GENERATE 语句
例:
CONSTANT NUM_OF_ADDERS = 8;
SUBDESIGN 4gentst
(
a[NUM_OF_ADDERS..1], b[NUM_OF_ADDERS..1], cin : INPUT;
c[NUM_OF_ADDERS..1], cout : OUTPUT;
)
VARIABLE
120
太原理工大学 夏路易
carry_out[(NUM_OF_ADDERS+1)..1] : NODE;
BEGIN
carry_out[1] = cin;
FOR i IN 1 TO NUM_OF_ADDERS GENERATE
c[i] = a[i] $ b[i] $ carry_out[i]; % Full Adder %
carry_out[i+1] = a[i] & b[i] # carry_out[i] & (a[i] $ b[i]);
END GENERATE;
cout = carry_out[NUM_OF_ADDERS+1];
END;
5)真值表语句
该语句用于指定组合逻辑和状态机的输入和输出行为。
例:
TABLE
a0, f[4..1].q => f[4..1].d, control;
(2) 保留识 别符
AHDL 中的保留识别符:
CARRY JKFFE SRFFE
CASCADE JKFF SRFF
CEIL LATCH TFFE
DFFE LCELL TFF
DFF M CELL TRI
EXP MEMORY USED
FLOOR OPENDRN WIRE
GLOBAL SOFT X
符号 功能
+ 加号
- 减
== 数和串相等
! NOT
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于
& AND
!& NAND
$ XOR
!$ XNOR
122
太原理工大学 夏路易
# OR
!# BOR
(4)AHDL 中的组
具有相同类型的端口可以形成一个组,该组可以有 256 个成员“BIT”,
如下的组虽然表达方式不同,但实际是同一个组。
b[5..0]
(b5, b4, b3, b2, b1, b0)
b[]
(5)AHDL 中的数
二进制例: B"0110X1X10"
八进制例: Q"4671223"
十六进制例:H"123AECF"
运算符 说明 优先级别
+ (unary)+1 positive 1
- (unary)-1 negative 1
! !a NOT 1
^ a^2 exponent 1
MOD 4 MOD 2 modulus 2
DIV 4 DIV 2 division 2
* a*2 multiplication 2
LOG2 LOG2(4-3) logarithm base2 2
+ 1+1 addition 3
- 1-1 subtraction 3
== (numeric) 5 == 5 numeric equality 4
== (string) "a" == "b" string equality 4
!= 5 != 4 not equal to 4
> 5>4 greater than 4
>= 5 >= 5 greater than or equal to 4
< a < b+2 less than 4
<= a <= b+2 less than or equal to 4
& a&b AND 5
AND a AND b
!& 1 !& 0 NAND (AND inverter) 5
NAND 1 NAND 0
$ 1 $ 1XOR (exclusive OR) 6
123
太原理工大学 夏路易
XOR 1 XOR 1
!$ ) 1 !$ 1 XNOR (exclusive NOR 6
XNOR 1 XNOR 1
# a#b OR 7
OR a OR b
!# a !# b NOR (OR inverter) 7
NOR a NOR b
? (5<4) ? 3:4 ternary 8
功能模块
Adders
Latches
Arithmetic Logic Units
Multipliers
Buffers
Multiplexers
Comparators
Parity Generators/Checkers
Converters
Rate Multipliers
Counters
Registers
Decoders
Shift Registers
Digital Filters
Storage Registers
EDAC
SSI Functions
Encoders
True/Complement I/O
Elements
Frequency Dividers
125
太原理工大学 夏路易
触发器和琐存器类:
DFF SRFF
DFFE
SRFFE
JKFF
TFF
JKFFE
TFFE
LATCH
输入输出端口类:
BIDIR
INOUT
INPUT
IN
OUTPUT
OUT
BIDIRC (GDFs only)
INPUTC (GDFs only)
OUTPUTC (GDFs only)
逻辑类:
AND
NOR
NOT
OR
XNOR
XOR
NAND
VCC (GDFs only)
BAND (GDFs only)
BNAND (GDFs only)
BNOR (GDFs only)
BOR (GDFs only)
GND (GDFs only)
SUBDESIGN decode1
(
address[15..0] : INPUT;
chip_enable : OUTPUT;
)
BEGIN
chip_enable = (address[15..0] == H"0370");
END;
在该例中当地址为十六进制数 370 时,输出端“chip_enable”输出高电平。
(3)布尔表达式 的使用
127
太原理工大学 夏路易
例 1:
SUBDESIGN boole1
(
a0, a1, b : INPUT;
out1, out2 : OUTPUT;
)
BEGIN
out1 = a1 & !a0;
out2 = out1 # b;
END;
例 2:具有一个声明的节点
SUBDESIGN boole2
(
a0, a1, b : INPUT;
out : OUTPUT;
)
VARIABLE
a_equals_2 : NODE; %被声明的节点%
BEGIN
a_equals_2 = a1 & !a0;
out = a_equals_2 # b;
END;
例 3:具有组的例。
OPTIONS BIT0 = MSB; %指定 BIT0 是 MSB%
CONSTANT MAX_WIDTH = 1+2+3-3-1; % 声明常数 MAX_WIDTH = 2 %
SUBDESIGN group1
(
a[1..2], use_exp_in[1+2-2..MAX_WIDTH] : INPUT;
d[1..2], use_exp_out[1+2*2-4..MAX_WIDTH] : OUTPUT;
dual_range[5..4][3..2] : OUTPUT;
)
BEGIN
d[] = a[] + B"10";
use_exp_out[] = use_exp_in[];
dual_range[][] = VCC;
128
太原理工大学 夏路易
END;
例 4:具有条件语句的例。
SUBDESIGN priority
(
low, middle, high : INPUT;
highest_level[1..0] : OUTPUT;
)
BEGIN
IF high THEN
highest_level[] = 3;
ELSIF middle THEN
highest_level[] = 2;
ELSIF low THEN
highest_level[] = 1;
ELSE
highest_level[] = 0;
END IF;
END;
在本例中, high 信号具有最高优先权,若三个信号 high,middle 和 low 都被 VCC 驱动,则
只有 high 信号起作用,输出 highest_level[] = 3。
例 5:有 CASE 的语句的例。
SUBDESIGN decoder
(
code[1..0] : INPUT;
out[3..0] : OUTPUT;
)
BEGIN
CASE code[] IS
WHEN 0 => out[] = B"0001";
WHEN 1 => out[] = B"0010";
WHEN 2 => out[] = B"0100";
WHEN 3 => out[] = B"1000";
END CASE;
END;
例 6: 7 段显示译码器例
129
太原理工大学 夏路易
7 段显示器的笔划顺序
% -a- %
% f| |b %
% -g- %
% e| |c %
% -d- %
该显示器可以显示如下数字和字母:
% 012345 6789AbCdEF %
7 段译码器程序:
SUBDESIGN 7segment
(
i[3..0] : INPUT;
a, b, c, d, e, f, g : OUTPUT;
)
BEGIN
TABLE
i[3..0] => a, b, c, d, e, f, g;
H"0" => 1, 1, 1, 1, 1, 1, 0;
H"1" => 0, 1, 1, 0, 0, 0, 0;
H"2" => 1, 1, 0, 1, 1, 0, 1;
H"3" => 1, 1, 1, 1, 0, 0, 1;
H"4" => 0, 1, 1, 0, 0, 1, 1;
H"5" => 1, 0, 1, 1, 0, 1, 1;
H"6" => 1, 0, 1, 1, 1, 1, 1;
H"7" => 1, 1, 1, 0, 0, 0, 0;
H"8" => 1, 1, 1, 1, 1, 1, 1;
H"9" => 1, 1, 1, 1, 0, 1, 1;
H"A" => 1, 1, 1, 0, 1, 1, 1;
H"B" => 0, 0, 1, 1, 1, 1, 1;
H"C" => 1, 0, 0, 1, 1, 1, 0;
H"D" => 0, 1, 1, 1, 1, 0, 1;
H"E" => 1, 0, 0, 1, 1, 1, 1;
H"F" => 1, 0, 0, 0, 1, 1, 1;
END TABLE;
130
太原理工大学 夏路易
END;
例 7:地址译码器例。
SUBDESIGN decode3
(
addr[15..0], m/io : INPUT;
rom, ram, print, sp[2..1] : OUTPUT;
)
BEGIN
TABLE
m/io, addr[15..0] => rom, ram, print, sp[];
1, B"00XXXXXXXXXXXXXX" => 1, 0, 0, B"00";
1, B"100XXXXXXXXXXXXX" => 0, 1, 0, B"00";
0, B"0000001010101110" => 0, 0, 1, B"00";
0, B"0000001011011110" => 0, 0, 0, B"01";
0, B"0000001101110000" => 0, 0, 0, B"10";
END TABLE;
END;
例 8:使用 lpm 译码功能译码
该译码器功能:
Enable data[LPM_WIDTH1..0] eq[LPM_DECODES-1..0]
0 X 0000...00
1 LPM_DECODES 1 1000...00
1 L_DECODES PM 2 0100...00
… … …
1 1 0000...10
1 0 0000...01
(
address[15..0] : INPUT;
chip_enable : OUTPUT;
)
BEGIN
chip_enable = lpm_decode(data[]=address[])
WITH (LPM_WIDTH=16, LPM_DECODES=2^10)
RETURNS (.eq[H"0370"]); %返回地址为 H"0370"位置的码%
END;
IF select_a THEN
wire_or = a;
wire_and = a;
END IF;
IF select_b THEN
wire_or = b;
wire_and = b;
END IF;
IF select_c THEN
wire_or = c;
wire_and = c;
END IF;
END;
BEGIN
DEFAULTS
/local_grant = VCC;
/request_out = VCC;
/grant_out = VCC;
END DEFAULTS;
IF /request_in == GND # /local_request == GND THEN
/request_out = GND;
END IF;
IF /grant_in == GND THEN
IF /local_request == GND THEN
/local_grant = GND;
ELSIF /request_in == GND THEN
/grant_out = GND;
END IF;
END IF;
END;
(4) 时序逻 辑
例 1:定义 D 触发器的输入输出信号。
SUBDESIGN bur_reg
(
clk, load, d[7..0] : INPUT;
q[7..0] : OUTPUT;
)
VARIABLE
ff[7..0] : DFFE;
BEGIN
ff[].clk = clk;
ff[].ena = load;
ff[].d = d[];
q[] = ff[].q;
END;
该例中分别定义 7 个 D 触发器的信号
134
太原理工大学 夏路易
例 2:调用巨功能模块
INCLUDE "lpm_dff.inc";
SUBDESIGN lpm_reg
(
clk, load, d[7..0] : INPUT;
q[7..0] : OUTPUT;
)
BEGIN
q[] = lpm_dff (.clock=clk, .enable=load, .data[]=d[])
WITH (LPM_WIDTH=8)
RETURNS (.q[]);
END;
例 3:在变量段声明寄存器的输出。
SUBDESIGN reg_out
(
clk, load, d[7..0] : INPUT;
q[7..0] : OUTPUT;
)
VARIABLE
q[7..0] : DFFE; % outputs also declared as registers %
BEGIN
q[].clk = clk;
q[].ena = load;
q[] = d[];
END;
例 4: 16 位计数器例
SUBDESIGN ahdlcnt
(
clk, load, ena, clr, d[15..0] : INPUT;
q[15..0] : OUTPUT;
)
VARIABLE
count[15..0] : DFF;
BEGIN
135
太原理工大学 夏路易
count[].clk = clk;
count[].clrn = !clr; %清零%
IF load THEN
count[].d = d[]; %置数%
ELSIF ena THEN
count[].d = count[].q + 1; %计数%
ELSE
count[].d = count[].q; %保持%
END IF;
q[] = count[];
END;
例 5:具有 D 触发器功能的状态机
SUBDESIGN simple
(
clk, reset, d : INPUT;
q : OUTPUT;
)
VARIABLE
ss: MACHINE WITH STATES (s0, s1);
BEGIN
ss.clk = clk;
ss.reset = reset;
CASE ss IS
WHEN s0 =>
q = GND;
IF d THEN
ss = s1;
END IF;
WHEN s1 =>
q = VCC;
IF !d THEN
ss = s0;
END IF;
END CASE;
136
太原理工大学 夏路易
END;
例 6:步进马达控制器
SUBDESIGN stepper
(
clk, reset : INPUT;
ccw, cw : INPUT;
phase[3..0] : OUTPUT;
)
VARIABLE
ss: MACHINE OF BITS (phase[3..0])
WITH STATES (
s0 = B"0001",
s1 = B"0010",
s2 = B"0100",
s3 = B"1000");
BEGIN
ss.clk = clk;
ss.reset = reset;
TABLE
ss, ccw, cw => ss;
%--------------------------------------------------%
s0, 1, x => s3;
s0, x, 1 => s1;
s1, 1, x => s0;
s1, x, 1 => s2;
s2, 1, x => s1;
s2, x, 1 => s3;
s3, 1, x => s2;
s3, x, 1 => s0;
END TABLE;
END;
(
clk : INPUT;
reset : INPUT;
y : INPUT;
z : OUTPUT;
)
VARIABLE
% current current %
% state output %
ss: MACHINE OF BITS (z)
WITH STATES (s0 = 0,
s1 = 1,
s2 = 1,
s3 = 0);
BEGIN
ss.clk = clk;
ss.reset = reset;
TABLE
% current current next %
% state input state %
ss, y => ss;
%-------------------------------------%
s0, 0 => s0;
s0, 1 => s2;
s1, 0 => s0;
s1, 1 => s2;
s2, 0 => s2;
s2, 1 => s3;
s3, 0 => s3;
s3, 1 => s1;
END TABLE;
END;
例 8:不声明输出状态的状态机
SUBDESIGN moore2
138
太原理工大学 夏路易
(
clk : INPUT;
reset : INPUT;
y : INPUT;
z : OUTPUT;
)
VARIABLE
ss: MACHINE WITH STATES (s0, s1, s2, s3);
zd: NODE;
BEGIN
ss.clk = clk;
ss.reset = reset;
z = DFF(zd, clk, VCC, VCC);
TABLE
% current current next next %
% state input state output %
ss, y => ss, zd;
s0, 0 => s0, 0;
s0, 1 => s2, 1;
s1, 0 => s0, 0;
s1, 1 => s2, 1;
s2, 0 => s2, 1;
s2, 1 => s3, 0;
s3, 0 => s3, 0;
s3, 1 => s1, 1;
END TABLE;
END;
例 9:异步状态机
SUBDESIGN mealy
(
clk : INPUT;
reset : INPUT;
y : INPUT;
z : OUTPUT;
)
139
太原理工大学 夏路易
VARIABLE
ss: MACHINE WITH STATES (s0, s1, s2, s3);
BEGIN
ss.clk = clk;
ss.reset = reset;
TABLE
% current current current next %
% state input output state %
ss, y => z, ss;
例 10:非指定状态的处理
例:
SUBDESIGN recover
(
clk : INPUT;
go : INPUT;
ok : OUTPUT;
)
VARIABLE
sequence : MACHINE
OF BITS (q[2..0])
WITH STATES (
idle,
one,
140
太原理工大学 夏路易
two,
three,
four,
illegal1,
illegal2,
illegal3);
BEGIN
sequence.clk = clk;
CASE sequence IS
WHEN idle =>
IF go THEN
sequence = one;
END IF;
WHEN one =>
sequence = two;
WHEN two =>
sequence = three;
WHEN three =>
sequence = four;
WHEN OTHERS => %其它状态转入 idle%
sequence = idle;
END CASE;
ok = (sequence == four);
END;
(
clk : INPUT;
out[15..0] : OUTPUT;
)
VARIABLE
counter : 4count;
decoder : 16dmux;
BEGIN
counter.clk = clk;
counter.dnup = GND;
decoder.(d,c,b,a) = counter.(qd,qc,qb,qa);
out[15..0] = decoder.q[15..0];
END;
142
太原理工大学 夏路易
143