You are on page 1of 30

太原理工大学 夏路易

3.5 用 AHDL 语言设 计数字系 统


AHDL 语言是 ALTERA 公司开发的高效、易学的硬件描述语言,在 max+plus2 软件中使
用它比 VHDL 语言更有效。

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;

(2) 定义函 数语句


该语句可以定义一个在分设计中使用函数,
例:
DEFINE MAX(a,b) = (a > b) ? a : b;
SUBDESIGN
(
dataa[MAX(WIDTH,0)..0]: INPUT;
datab[MAX(WIDTH,0)..0]: OUTPUT;
)
BEGIN
datab[] = dataa[];
END;
此例中 MAX 函数保证最小的数据位宽度。

(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
太原理工大学 夏路易

RETURNS (MACHINE ss_out);

(5) 最小位 数选择语 句


定义一组数据中的最小数位是否是 MSB ( most significant bit )或 LSB ( least significant
bit)
例:
OPTIONS BIT0 = MSB;

(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;

0, B"0000" => B"0001", 1;


0, B"0100" => B"0010", 0;
1, B"0XXX" => B"0100", 0;
X, B"1111" => B"0101", 1;
END TABLE;
该例中,a0 和 f[4..1].q 是输入,f[4..1].d 和 control 是输出,

3.5.2 AHDL 中的语言元 素

(1)AHDL 中的保 留关键字


AHDL 语言建议用大写字母书写如下关键字:
AND FUNCTION OUTPUT
ASSERT GENERATE PARAMETERS
BEGIN GND REPORT
BIDIR HELP_ID RETURNS
BITS IF SEGMENTS
BURIED INCLUDE SEVERITY
CASE INPUT STATES
CLIQUE IS SUBDESIGN
CONNECTED_PINS LOG2 TABLE
121
太原理工大学 夏路易

CONSTANT MACHINE THEN


DEFAULTS MOD TITLE
DEFINE NAND TO
DESIGN NODE TRI_STATE_NODE
DEVICE NOR VARIABLE
DIV NOT VCC
ELSE OF WHEN
ELSIF OPTIONS WITH
END OR XNOR
FOR OTHERS XOR

(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

(3) AHDL 中运算符

符号 功能
+ 加号
- 减
== 数和串相等
! 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"

(6)AHDL 中的算 数表达式

运算符 说明 优先级别
+ (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

( 7)巨功能模 块( LPM 功能)


Mega 功能模块列表:
门类:
lpm_and lpm_inv
lpm_bustri lpm_mux
lpm_clshift lpm_or
lpm_constant lpm_xor
lpm_decode mux
busmux
运算类:
lpm_abs lpm_counter
lpm_add_sub lpm_mult
lpm_compare
存储类:
csfifo lpm_ram_dq
csdpram lpm_ram_io
lpm_ff lpm_rom
lpm_latchlpm_dff (for backward compatibility only)
lpm_shiftreg lpm_tff (for backward compatibility only)
其它类:
clklock pll
ntsc
核心类:
a16450 a8255
a6402 fft
a6850 rgb2ycrcb
a8237 ycrcb2rgb
a8251
124
太原理工大学 夏路易

具体的功能块输入输出信号见 Max+plusⅡ 软件帮助。

(8)老逻辑功能 块( Old-Style Macrofunctions)和宏 功能块( Macrofunction)


分类列表:

功能模块
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

具体的功能块输入输出信号见 Max+plusⅡ 软件帮助。

(9)基本逻辑功 能块( Primitives)


缓冲器类:
CARRY
OPNDRN
CASCADE
SOFT
EXP TRI
GLOBAL (SCLK)
WIRE (GDFs only)
LCELL (MCELL)

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)

具体的功能块的功能和输入输出信号见 Max+plusⅡ 软件帮助。

3.5.3 AHDL 的使用例子

(1)使用 AHDL 中的数


例 1:
126
太原理工大学 夏路易

SUBDESIGN decode1
(
address[15..0] : INPUT;
chip_enable : OUTPUT;
)
BEGIN
chip_enable = (address[15..0] == H"0370");
END;
在该例中当地址为十六进制数 370 时,输出端“chip_enable”输出高电平。

(2)常数和定义 函数功能 的使用


例 1:常数使用例。
CONSTANT IO_ADDRESS = H"0370"; %常数%
SUBDESIGN decode2
(
a[15..0] : INPUT;
ce : OUTPUT;
)
BEGIN
ce = (a[15..0] == IO_ADDRESS);
END;
例 2:定义函数使用例。
PARAMETERS (WIDTH);
DEFINE MAX(a,b) = (a > b) ? a : b; % 使用定义功能定义的函数,该函数保证端口位数的数
量%
SUBDESIGN minport
(
dataA[MAX(WIDTH,0)..0] : INPUT;
dataB[MAX(WIDTH,0)..0] : OUTPUT;
)
BEGIN
dataB[] = dataA[];
END;

(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

该函数的 AHDL 说明:


FUNCTION lpm_decode (data[LPM_WIDTH-1..0], enable, clock, aclr)
WITH (LPM_WIDTH, LPM_DECODES, LPM_PIPELINE)
RETURNS (eq[LPM_DECODES-1..0]);
在此例中不需要 enable,clock 和 acir 端口。
该译码器源文件:
INCLUDE "lpm_decode.inc";
SUBDESIGN decode4
131
太原理工大学 夏路易

(
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;

(4) 变量缺 省值的使 用


例 1:
SUBDESIGN default1
(
i[3..0] : INPUT;
ascii_code[7..0] : OUTPUT;
)
BEGIN
DEFAULTS
ascii_code[] = B"00111111"; % 问号的 ASCII 码 %
END DEFAULTS;
TABLE
i[3..0] => ascii_code[];
B"1000" => B"01100001"; % "a" %
B"0100" => B"01100010"; % "b" %
B"0010" => B"01100011"; % "c" %
B"0001" => B"01100100"; % "d" %
END TABLE;
END;
在该例中若没有译码输出时,输出问号。
例 2:
SUBDESIGN default2
(
a, b, c : INPUT;
select_a, select_b, select_c : INPUT;
132
太原理工大学 夏路易

wire_or, wire_and : OUTPUT;


)
BEGIN
DEFAULTS
wire_or = GND;
wire_and = VCC;
END DEFAULTS;

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;

(5) 低电平 激活信号


例 1:
SUBDESIGN daisy
(
/local_request : INPUT;
/local_grant : OUTPUT;
/request_in : INPUT;
/request_out : OUTPUT;
/grant_in : INPUT;
/grant_out : OUTPUT;
)
133
太原理工大学 夏路易

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;

例 7:指定一个输出 BIT 的状态机


SUBDESIGN moore1
137
太原理工大学 夏路易

(
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;

s0, 0 => 0, s0;


s0, 1 => 1, s1;
s1, 0 => 1, s1;
s1, 1 => 0, s2;
s2, 0 => 0, s2;
s2, 1 => 1, s3;
s3, 0 => 0, s3;
s3, 1 => 1, s0;
END TABLE;
END;

例 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;

(6)基本逻辑模 块 /老型号 宏功能模 块 /某些巨 功能模块 的使用


这 些 模 块 放 在 \maxplus2\max2lib\mega_lpm 和 \maxplus2\max2inc 子 目 录 中 , 使 用 包 括
(Include)语句,可以使的这些文件在 TDF 文件中使用。
使用方法:
1. 在变量段声明这些模块的引用变量
2. 在逻辑段用<引用名>.<端口名>的格式使用端口
如下例子是四位计数器连接四/十六译码器,这些模块的引用在变量段的引用声明说明的。
INCLUDE "4count";
INCLUDE "16dmux";
SUBDESIGN macro1
141
太原理工大学 夏路易

(
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;

该例子中使用了 ALTERA 提供的宏函数 4count 和 16dmux,它们在变量段给予了声明,


使 counter 代表 4count ,decoder 代表 16dmux ,两个函数的输入口以 <引用名>.<端口名>的
格式在逻辑段布尔表达式的左边,输出口以同样的方式放在右边。

这两个被引用的函数放在 4count.inc 和 16dmux.inc 文件中,定义如下:


FUNCTION 4count (clk, clrn, setn, ldn, cin, dnup, d, c, b, a)
RETURNS (qd, qc, qb, qa, cout);
FUNCTION 16dmux (d, c, b, a)
RETURNS (q[15..0]);

( 7)创造宏功 能和巨功 能模块


创造一个 AHDL 能用的宏功能和巨功能模块需要如下步骤:
1)编译和仿真设计文件以保证设计的正确性
2)最好建立一个专门的子目录放设计文件
3)打开文本编辑器窗口,调入设计文件
4)选择 File/Create Default Include File 菜单建立 TDF 能使用的包括文件
5)选择 File/Create Default Symbol 菜单建立图形编辑器能使用的符号文件

142
太原理工大学 夏路易

143

You might also like