Download presentation
Presentation is loading. Please wait.
1
EDA技术基础 CPLD技术及其应用
2
硬件描述语言 — AHDL
3
什么是 AHDL Altera Hardware Description Language 由Altera公司开发
集成在Altera软件 Max+Plus II中 描述硬件用语言而不是图形 容易建立 容易修改 对以下设计非常优越 复杂的组合逻辑 BCD 到 7 段编码转换 地址译码 状态机 其他…
4
什么是 AHDL 续… 和图形输入一样容易 和其他硬件描述语言一样强大
如HDL (Hardware Description Language) VHDL, Verilog HDL 等
5
首先建立工程 Project…
6
怎样使用 ADHL 可使用任何文本编辑器创建文件 Altera软件 Max+Plus II 提供文本编辑器
Type in your AHDL design file 可使用任何文本编辑器创建文件 Altera软件 Max+Plus II 提供文本编辑器
7
创建你的 AHDL 文件 续.
8
两处须同名 保存 ADHL 文件名为 xxxx.TDF 续.
11
当前工程名
12
续...
13
AHDL设计的附加选项
14
打开 Max+Plus II 附加选项 有些内置的附加选项对工程师在使用AHDL 设计进程中有所帮助 选项菜单中的语法色彩选项 将这一选项
On/Off 绿色表示注释 兰为ADHL 保留字
15
用户可自行修改颜色选项 使用选项菜单中的调色板,自定义如下颜色:
comments, illegal characters, megafunctions, macrofuncitons? 可选元素 颜色选定
16
编译过程中的错误定位 很容易定位错误 错误定位 双击错误信息 点击定位按钮
17
AHDL 模板 忘记怎么办? If-then-else case-end case loop-end loop ?????
18
使用 AHDL 模板
19
使用AHDL模板
20
使用AHDL模板
21
使用AHDL模板 修改代码
22
使用 Help 选项
28
AHDL程序规范
29
AHDL 程序架构 可选 必须 Subdesign Section Variable Section Logic Section
Title Statement Include Statement Constant Statement Define Statement Parameters Statement Function Prototype Statement Options Statement Design Section Subdesign Section Variable Section Logic Section AHDL 可选 程序架构 必须
30
AHDL 书写格式 SUBDESIGN file_name ( input_pin_name : INPUT;
input_bus_name[15..0] : INPUT; output_pin_name : OUTPUT; output_bus_name : OUTPUT; ) BEGIN ouptut_pin_name = input_pin_name; output_bus_name = input_bus_name; END; 关键字 定义 I/O 口 逻辑项
31
引 言
32
1、使用数字
33
使用数字 SUBDESIGN decode1 ( address[15..0] : INPUT; chip_enable : OUTPUT;
数字是用来定义布尔表达式、方程、算术表达式及参数中的常数值,AHDL支持十进制、二进制、八进制及十六进制数。 SUBDESIGN decode1 ( address[15..0] : INPUT; chip_enable : OUTPUT; ) BEGIN chip_enable = (address[15..0] == H"0370"); END; 在此例中,十进制数15-0用来定义地址总线的比特位, 十六进制数H“0370”用来定义被译码的地址。
34
AHDL设计1 – 地址译码器 Graph? a0 a1 a2 a3 SUBDESIGN decode1 a4
chip_enable a0 a2 a1 a3 a4 a5 a6 a7 a9 a15 a10 a11 a12 a13 a14 a8 SUBDESIGN decode1 ( a[15..0] : INPUT; chip_enable : OUTPUT; ) BEGIN chip_enable = (a[15..0] == H“370"); END;
35
AHDL设计1 – 地址译码器 AHDL ? SUBDESIGN decode1 a0 ( a[3..0] : INPUT;
chip_enable : OUTPUT; ) BEGIN chip_enable = (a[3..0] == H"7"); END; a2 a1 a0 a3 chip_enable chip_enable = a0 & a1 & a2 & !a3
36
相关问题 – 数字的使用 例: B"0110X1X10" Radix: Values:
Decimal <series of digits 0 to 9> Binary B"<series of 0's, 1's, X's>" (where X = "don't care") Octal O"<series of digits 0 to 7>" or Q"<series of digits 0 to 7>" Hexadecimal X"<series from 0 to 9, A to F>" or H"<series from 0 to 9, A to F>" 例: B"0110X1X10" Q" " H"123AECF"
37
为什么使用 AHDL 而不用图形 易于修改 电路由代码表示 SUBDESIGN decode1 ( a[3..0] : INPUT;
chip_enable : OUTPUT; ) BEGIN chip_enable = (a[3..0] == H"A"); END; Chip_enable = !a0 & a1 & !a2 & a3 a2 a1 a0 a3 chip_enable 修改费力 自动解释功能 仅改此处
38
更有甚者 SUBDESIGN decode1 ( a[3..0] : INPUT; chip_enable : OUTPUT; )
BEGIN chip_enable = (a[3..0] == B"1x0x"); END; 有些bit位在比较时可忽略
39
需要了解的运算符号 Addition : + Subtraction : - Numeric Equality : ==
Not equal to : != Greater than : > Greater than or equal to : >= Less than : < Less than or equal to : <= Logical OR : # Logical AND : &
40
赋值问题 B“00001011” 而不是 B“00100011” B“001011” 而不是 B“00100011”,位数不匹配,出错。
a[7..0] = (H“2”, H“3”) 编译器翻译为 B“ ” 而不是 B“ ” a[7..0] = (B"0010", H"3") 编译器翻译为 B“001011” 而不是 B“ ”,位数不匹配,出错。 建议:用二进制写全。
41
2、使用常数和求值函数
42
使用常数 CONSTANT IO_ADDRESS = H"0370"; SUBDESIGN decode2 (
a[15..0] : INPUT; ce : OUTPUT; ) BEGIN ce = (a[15..0] == IO_ADDRESS); END;
43
使用常数功能 CONSTANT IO_ADDRESS = H"A"; 一处修改 SUBDESIGN decode1
定义CONSTANT在关键字SUBDESIGN之前 CONSTANT IO_ADDRESS = H"A"; SUBDESIGN decode1 ( a[3..0] : INPUT; chip_enable : OUTPUT; ) BEGIN chip_enable = (a[3..0] == IO_ADDRESS); IF(a[3..0] == IO_ADDRESS) THEN ... END; 一处修改 各处自动替换
44
有关常数的进一步定义 Constant example CONSTANT IO_ADDRESS = H“70”
CONSTANT FOO = 1+2*3 - LOG2(256); CONSTANT FOO_PLUS_one = FOO + 1; 定义一个常数值 定义一个算法式 依靠前一定义值
45
以下示例定义常数 FAMILY,然后使用它在 Assert 陈述中来检查现在的器件是否是 FLEX 8000系列。
PARAMETERS ( DEVICE_FAMILY % DEVICE_FAMILY is a predefined Altera parameter % ); CONSTANT FAMILY = "FLEX8000"; SUBDESIGN strcmp a : INPUT; b : OUTPUT; ) BEGIN IF (DEVICE_FAMILY == FAMILY) GENERATE ASSERT REPORT "Detected compilation for FLEX8000 family" SEVERITY INFO; b = a; ELSE GENERATE REPORT "Detected compilation for % family" DEVICE_FAMILY SEVERITY ERROR; END GENERATE; END;
46
使用求值函数 使用DEFINE定义求值函数 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;
47
3、定义组
48
定义组 组可以用下列三中方式声明: 1、一个单域组包含符号名或端口名,后随用方括弧括起的单域。例: a[4..1] 。
一旦组被定义,[]就可用来简化定义整个域。 一个单数字可用来替换一个域,例: a[5] ,此时和a5 等价。 2、一个双域组包含符号名或端口名,后随用方括弧括起的双域。例: d[6..0][2..0] 。 双于域组被用来设计两维总线结构。一旦组被定义,[][]就可用来简化定义整个域。一个单独的节点可被命名为 name[y][z] 或 name y_z 。 y和z 为数字。 3、一个序列组包含一个符号名、端口和数字的列表 ,以逗号分隔,以圆括弧括起。例: (a, b, c) 。单域和双域也可以列表用圆括弧括起或作为列表内容。例:(a、b、c[5..1]) 。 定义组示例: b[5..0] (b5, b4, b3, b2, b1, b0) b[] b[log2(256) ] b[2^8..3 mod 1] b[2*8..8 div 2]
49
定义组 例:单域名组 a[4..1] 包含节点a4、a3、a2、a1。
一个组(GROUP)最多包含256个成员或BITS,当作一个节点集看待,操作时当作一个整体。一个组可定义为单域名、双域名或序列域名形式。 例:单域名组 a[4..1] 包含节点a4、a3、a2、a1。 双域名组 a[2..1][5..3] 包含节点a2_5、a2_4、a2_3、a1_5、a1_4、a1_3。 序列域名 (a、b、c)包含节点a、b、c 。 在布尔方程中,一个组可被赋予一个布尔表达式、其他组、一个单节点、VCC、GNG、1或0。在每一种情况中,组获得的值是不同的。 Options 说明可用于定义组中最低数字的比特位是MSB还是LSB。 1、一旦组被定义,[]就可用来简化定义整个域。例:a[4..1] 可被缩写为a[] ,同样, b[5..4][3..2]可简写为 b[][]。 2、为避免混淆组名,在组名中禁止使用数字尾缀。例:编译器分不清组 q1[15..0] 和 q11[15..0]。
50
组的定义–实例 OPTIONS BIT0 = MSB;
CONSTANT MAX_WIDTH = ; % MAX_WIDTH = 2 % SUBDESIGN group1 ( a[1..2], use_exp_in[ 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; END;
51
组使用说明: 当组被其他组赋值且大小相等时,按照排序位置一一对应。 例:d[2..0]=q[8..6]---d2-q8,d1-q7,d0-q6 当一个组被赋予一个单节点,则所有的位都接到节点上。 例:d[2..0]=n。 当一个组被接到VCC或 GND, 所有位都赋予1或0值。 例: d[2..0]=VCC。 当一个组被接到十进制1上,仅LSB位接VCC,其他接GND。 例: d[2..0]=1。 等效于d[2..0]=B”001”。 尽量不造成组不匹配情况
52
组操作 a0 out0 b0 功能同样更容易 a1 out1 b1 a2 out2 b2 a3 out3 b3
SUBDESIGN decode1 ( a[3..0], b[3..0] : INPUT; out[3..0] : OUTPUT; ) BEGIN out0 = a0 & b0; out1 = a1 & b1; out2 = a2 & b2; out3 = a3 & b3; END; a0 b0 out0 a1 b1 out1 a2 b2 out2 a3 b3 out3 功能同样更容易 SUBDESIGN decode1 ( a[3..0], b[3..0] : INPUT; out[3..0]: OUTPUT; ) BEGIN out1[] = a[] & b[]; END;
53
组操作渐进 组操作 a[9..0], b[9..0] a[] = b[]; a[7..4] = b[9..6];
a[9..8] = VCC; a[9..8] = 1; a[9..8] = 2; a[9..8] = 3; a[3..0] = GND a[3..0] = 0; temp = b0& b1; a[2..1] = temp a7=b9, a6=b8, a5=b7, a4=b6 a[9..8] connect to VCC a[9..8] = B“01” a[9..8] = B“10” a[9..8] = B“11” a[3..0] connect to GND a[3..0] = B”0000” a2 = temp, a1 = temp
54
组操作更进 Bus [Group] b[3..0] ARRAY BUS [Group] a[3..0][2..0]
b3, b2, b1, b0 (有4个成员) MSB is b3, LSB is b0 ARRAY BUS [Group] a[3..0][2..0] a3_2, a3_1, a3_0, a2_2, a2_1, a2_0, a1_2, a1_1, a1_0, a0_2, a0_1, a0_0 (有12 个成员) MSB is a3_2, LSB is a0_) a[3..2][1..0] = b[]; 后面先改变 a3_1 = b3 a3_0 = b2 a2_1 = b1 a2_0 = b0
55
组合逻辑
56
综合布尔表达式和方程 ------陈述句
57
综合组合逻辑 AHDL ? Graphic SUBSDESIGN boole1 ( a0, a1, b : INPUT; a0
out1, out2 : OUTPUT; ) BEGIN out1 = a0 & !a1; out2 = out1 # b; END; a0 a1 b out1 out2 out1 = a0 & !a1 out2 = a0 & !a1 # b
58
定义节点
59
声明节点 SUBDESIGN boole2 ( a0, a1, b : INPUT; out : OUTPUT; ) a0 VARIABLE
a_equals_2 : NODE; BEGIN a_equals_2 = a1 & !a0; out = a_equals_2 # b; END; a0 a1 b a_equals_2 out
60
声明节点 AHDL ? SUBDESIGN boole3 a0 temp ( a0, a1, b, d: INPUT;
out2, out3 : OUTPUT; ) VARIABLE temp : NODE; BEGIN temp = a0 & !a1; out2 = temp # b; out3 = temp & d; END; a0 a1 b out3 out2 d temp out2 = a0 & !a1 # b out3 = a0 & !a1 & d
61
节点分为普通节点(关键字NODE)和三态节点(关键字TRI_STATE_NODE) 。 NODE 和 TRI_STATE_NODE 的不同在于多重分配时产生不同的结果:
对于NODE 的多重分配,是将信号线集总起来实现线与(wired-AND)或者线或(wired-OR )功能。在 Defaults 声明中昭示的变量缺省值决定其行为:缺省值为 VCC 产生 wired-AND功能;缺省值为GND 产生 wired-OR 功能。 多重分配对于TRI_STATE_NODE 意味着将信号线接于同一节点。 如果只有一个信号线接于 TRI_STATE_NODE, 该节点当着 NODE看待。
62
变量部分声明
63
变量部分声明 普通节点 实例声明 三态节点 VARIABLE 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; 普通节点 实例声明 三态节点
64
命名规则
65
引用和非引用命名 符号名是用户在AHDL中自定义的标识符,常用于TDF文件中的以下部分的命名:
-内部(临时定义)和外部(输入输出端口)的节点和组 -常数 -状态机名、状态位和状态名 -实例 -参数 -存储器段 -求值函数 -指定操作 Subdesign 名是用户自定义的子设计文件名。 Subdesign 名必须和TDF文件名一致。 端口名是用来确定逻辑函数输入输出的符号名。 编译器产生的命名包含“~”符号,出现在工程的适配文件Fit File中。如果反注 Fit File 分配表,这些命名将出现在工程的ACF文件中。 “~”符号仅是编译器产生命名的保留符号,不能用于用户文档的管脚、节点和组的命名。
66
规则列表 例:合法的非引用型命名 a /a1 非法的非引用型命名 -foo node 55
有两种符号可以出现在subdesign, symbolic, 及 port 命名中: 引用和非引用型。引用型就是用(‘) 把字符串括起来,而非引用型则无。 例:合法的非引用型命名 a /a1 非法的非引用型命名 -foo node 55 合法的引用型命名 ‘ -bar ’ ‘ table ’ ‘ 1221 ’ 非法的引用型命名 ‘bowling4$’ ‘has a space’ ‘a_name_with_more_than_32_characters’ 规则列表 Legal Name Unquoted Quoted Unquoted Quoted Unquoted Quoted Characters Subdesign Subdesign Symbolic Symbolic Port Port Name Name Name Name Name Name A-Z Yes Yes Yes Yes Yes Yes a-z Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Underscore (_) Yes Yes Yes Yes Yes Yes Slash (/) No No Yes Yes Yes Yes Dash (-) No Yes No Yes No Yes Digits only (0-9) Yes Yes No Yes Yes Yes Keyword No Yes No Yes No Yes Identifier No Yes No No No Yes Max. Characters
67
保留关键字 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 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
68
保留标示符 CARRY JKFFE SRFFE CASCADE JKFF SRFF CEIL LATCH TFFE
DFFE LCELL TFF DFF MCELL TRI EXP MEMORY USED FLOOR OPENDRN WIRE GLOBAL SOFT
69
运算进阶 操作符/ 举例: 描述 优先级 比较符: + (unary) +1 正 1 - (unary) -1 负 1 ! !a 非 1
操作符/ 举例: 描述 优先级 比较符: + (unary) 正 1 - (unary) 负 1 ! !a 非 1 ^ a ^ 指数 1 MOD MOD 取模 2 DIV DIV 除 2 * a * 乘 2 LOG2 LOG2(4-3) 底2对数 2 加 3 减 3 == (numeric) 5 == 数字等 4 == (string) “a” == “b” 字符串等 4 运算进阶
70
运算进阶 操作符/ 举例: 描述 优先级 比较符: != 5 != 4 不等于 4 > 5 > 4 大于 4
操作符/ 举例: 描述 优先级 比较符: != 5 != 4 不等于 4 > 5 > 4 大于 >= >= 5 大于等于 4 < a < b+2 小于 <= a <= b+2 小于等于 4 & a & b 与 AND a AND b !& !& 0 与非 (与取反) 5 NAND NAND 0 $ $ 1 异或 XOR XOR 1 !$ !$ 1 异或非 6 XNOR XNOR 1 # a # b 或 OR a OR b !# a !# b 或非 (或取反) 7 NOR a NOR b ? (5<4) ? 3:4 三变数 8 运算进阶
71
DEFINE---定义描述
72
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;
73
条件逻辑综合
74
AHDL IF描述逻辑 Graphic high Highest_level1 middle Highest_level0 low
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; Graphic Highest_level1 Highest_level0 high middle low
75
Case 描述 CASE f[].q IS WHEN H"00" => addr[] = 0; s = a & b;
count[].d = count[].q + 1; WHEN H"02", H"03", H"04" => f[3..0].d = addr[4..1]; WHEN OTHERS => f[].d = f[].q; END CASE;
76
Case 描述逻辑 Graphic code0 out0 code1 out1 out2 out3 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; out2 out1 out0 out3 code1 code0
77
If Then描述 与 Case描述
78
If Then 描述差异 If Then 描述1 Compiler 翻译 If Then 描述2 IF a THEN c = d;
ELSIF b THEN f = e; END IF; Compiler 翻译 IF a THEN c = d; END IF; IF !a & b THEN f = e; If Then 描述2 IF a THEN c = d; END IF; IF b THEN f = e;
79
If Then 描述 Compiler 翻译 IF a THEN IF a THEN c = d; c = d; END IF;
ELSIF b THEN IF !a & b THEN c = e; c = e; ELSE IF !a & !b THEN c = f; c = f; END IF; END IF;
80
If Then 描述 与 Case 描述 If Then 描述 Case 描述 CASE a[] IS
IF a[] == 0 THEN WHEN 0 => y = c & d; y = c & d; ELSIF a[] == 1 THEN WHEN 1 => y = e & f; y = e & f; ELSIF a[] == 2 THEN WHEN 2 => y = g & h; y = g & h; ELSIF a[] == 3 THEN WHEN 3 => y = i; y = i; ELSE WHEN OTHERS => y = GND; y = GND; END IF; END CASE;
81
IF-THEN-ELSE 与 CASE比较 If-then-else 与 CASE相似 有些情况下使用任何一种都能达到同样的结果
这两个条件可能完全无关 条件必须是同样的 CASE a[] IS WHEN 0 => y=c&d; WHEN 1 => IF a[] == 0 THEN y=c&d; ELSIF b == 0 THEN z = x#y; END IF;
82
比较实例 SUBDESIGN decoder (low, medium, high : INPUT;
highest_level[3..0] : OUTPUT; ) VARIABLE code[2..0] : NODE; BEGIN code2=high; code1=medium; code0=low; CASE code[] IS WHEN 4 => highest_level[] = B"1000"; WHEN 2 => highest_level[] = B"0100"; WHEN 1 => highest_level[] = B"0010"; WHEN OTHERS => highest_level[] = B"0001"; END CASE; END; SUBDESIGN priority ( low, middle, high : INPUT; highest_level[3..0] : OUTPUT; ) BEGIN IF high THEN highest_level[] = B“1000”; ELSIF middle THEN highest_level[] = B“0100”; ELSIF low THEN highest_level[] = B“0010”; ELSE highest_level[] = B“0001”; END IF; END;
83
IF-THEN-ELSE AHDL Graphic high Highest_level3 middle Highest_level2
SUBDESIGN priority ( low, middle, high : INPUT; highest_level[3..0] : OUTPUT; ) BEGIN IF high THEN highest_level[] = B“1000”; ELSIF middle THEN highest_level[] = B“0100”; ELSIF low THEN highest_level[] = B“0010”; ELSE highest_level[] = B“0001”; END IF; END; high low middle Highest_level3 Highest_level2 Highest_level1 Highest_level0
84
需要 4个 LCELL
85
进一步考察 IF-THEN-ELSE IF-THEN-ELSE 可实现按优先级编码 为什么?? 当
high=1, middle=1, low=1 ? high=0, middle=1, low=1 ? high=1, middle=1, low=0 ? high=1, middle=0, low=0 ? highest_level[] 输出是什么? high=1, middle=x, low=x high=0, middle=1, low=x high=1, middle=x, low=x high=1, middle=x, low=x high low middle Highest_level3 Highest_level2 Highest_level1 Highest_level0
86
Case 陈述举例 high /high medium /medium low /low Graphic?
Highest_level3 high /high medium /medium low /low Highest_level2 Highest_level1 Highest_level0 Case 陈述举例 SUBDESIGN decoder (low, medium, high : INPUT; highest_level[3..0] : OUTPUT; ) VARIABLE code[2..0] : NODE; BEGIN code2=high; code1=medium; code0=low; CASE code[] IS WHEN 4 => highest_level[] = B"1000"; WHEN 2 => highest_level[] = B"0100"; WHEN 1 => highest_level[] = B"0010"; WHEN OTHERS => highest_level[] = B"0001"; END CASE; END; Graphic? 此处声明有何用
88
进一步考察 CASE Statement CASE 不能实现按优先级编码 为什么?? 当 highest_level[] 输出是什么?
high=0, middle=1, low=1 ? high=1, middle=1, low=1 ? high=1, middle=1, low=0 ? high=1, middle=0, low=0 ? highest_level[] 输出是什么? Highest_level3 high /high medium /medium low /low Highest_level2 Highest_level1 Highest_level0
89
创建译码器举例 ----真值表法
90
创建译码器 a g d a g d a g d a g d a g d a g d a g d a g d a g d a g d a g
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; END; 创建译码器 a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e 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;
91
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" " => 0, 0, 1, B"00"; 0, B" " => 0, 0, 0, B"01"; 0, B" " => 0, 0, 0, B"10"; END TABLE; END;
92
INCLUDE "lpm_decode.inc";
SUBDESIGN decode4 ( 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"]); END;
93
变量缺省值的使用
94
何处使用 Default 通常应用于节点和组 当节点和组在 AHDL 文档中有些地方没有指定时
95
使用 Default SUBDESIGN decoder ( low, medium, high : INPUT;
highest_level[3..0] : OUTPUT; ) VARIABLE code[2..0] : node; BEGIN DEFAULTS highest_level[] = B"0001"; END DEFAULTS; code2=high; code1=medium; code0=low; CASE code[] IS WHEN 4 => highest_level[] = B"1000"; WHEN 2 => highest_level[] = B"0100"; WHEN 1 => highest_level[] = B"0010"; END CASE; END;
96
变量缺省值 SUBDESIGN default1 ( i[3..0] : INPUT; ascii_code[7..0] : OUTPUT;
) BEGIN DEFAULTS ascii_code[] = B" "; % ASCII question mark "?" % END DEFAULTS; TABLE i[3..0] => ascii_code[]; B"1000" => B" "; % "a" % B"0100" => B" "; % "b" % B"0010" => B" "; % "c" % B"0001" => B" "; % "d" % END TABLE; END;
97
竞争实例 1 SUBDESIGN default2 ( a,b : INPUT; select_a, select_b : INPUT;
out1 : OUTPUT; ) BEGIN DEFAULTS out1 = GND; END DEFAULTS; IF select_a THEN out1 = a; END IF; IF select_b THEN out1 = b; END; a or b Normal Default SELECT_A A SELECT_B B out1
98
竞争实例 2 SUBDESIGN default2 ( a,b : INPUT; select_a, select_b : INPUT;
out1 : OUTPUT; ) BEGIN DEFAULTS out1 = VCC; END DEFAULTS; IF select_a THEN out1 = a; END IF; IF select_b THEN out1 = b; END; a and b Normal Default SELECT_A A SELECT_B B out1
99
变量缺省值 Graphic? SELECT_A A SELECT_B WIRE_OR B SELECT_C C WIRE_AND
SUBDESIGN default2 ( a, b, c : INPUT; select_a, select_b, select_c : INPUT; 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; IF select_c THEN wire_or = c; wire_and = c; END; 变量缺省值 Graphic? SELECT_A A SELECT_B B SELECT_C C WIRE_OR WIRE_AND
100
低有效电路综合
101
菊花链总线仲裁电路 —优先级电路 单元电路 低有效典型电路 /LoR— 低一级请求 /LoG— 低一级允许 /LR— 本地请求
/LG— 本地允许 /HiR— 向高一级请求 /HiR—高一级允许 /LoR /LoG /LR /HiR /HiG /LG 单元电路
102
菊花链总线仲裁电路 —优先级电路 菊花链接 低有效典型电路 最高级 中间级 最低级 /LoR /LoG /LR /HiR /HiG /LG
GND
103
低有效典型电路 Graphic SUBDESIGN daisy ( /LR : INPUT; /LG : OUTPUT;
/LoR : INPUT; % from lower priority % /LoG : OUTPUT; % to lower priority % /HiR : OUTPUT; % to higher priority % /HiG : INPUT; % from higher priority % ) BEGIN DEFAULTS /LG = VCC; % active-low output % /LoG = VCC; % signals should default % /HiR = VCC; % to VCC % END DEFAULTS; IF (/LoR == GND) # (/LR == GND) THEN /HiR = GND; END IF; IF( /HiG == GND )THEN IF( /LR == GND )THEN /LG = GND; ELSIF( /LoR == GND )THEN /LoG = GND; Graphic /LoR /LoG /LR /HiR /HiG /LG
104
典型电路细化 /LoR /LoG /LR /HiR /HiG /LG Graphic /HiR /HiG /LoR /LoG /LR /LG
105
For 循环 用同样的方程更容易 CONSTANT num_of_bit = 8; SUBDESIGN numbit
( a[num_of_bit..0] : input; b[num_of_bit..0] : output; ) BEGIN FOR i IN 0 TO num_of_bit GENERATE b[num_of_bit - i] = a[i]; END GENERATE; END; CONSTANT num_of_bit = 8; SUBDESIGN numbit ( a[num_of_bit..0] :INPUT; b[num_of_bit..0] :OUTPUT; ) BEGIN b[8] = a[0]; b[7] = a[1]; b[6] = a[2]; b[5] = a[3]; b[4] = a[4]; b[3] = a[5]; b[2] = a[6]; b[1] = a[7]; b[0] = a[8]; END; 用同样的方程更容易 CONSTANT num_of_bit = 8; SUBDESIGN numbit (a[num_of_bit..0] : INPUT; b[num_of_bit..0] : OUTPUT; ) BEGIN b[num_of_bit..0] = a[0..num_of_bit]; END;
106
AHDL 使用图形方式 使用 File 菜单为AHDL 设计文档创建 Symbol 这个 symbol 可用作图形输入
107
寄存器逻辑
108
寄存器引用 原形函数 电路图形 方法2 先声明,后成员赋值 方法1 直接代换 默认
D CLK Q PRN CLRN 电路图形 FUNCTION DFF (D, CLK, CLRN, PRN) RETURNS (Q); 原形函数 方法2 先声明,后成员赋值 SUBDESIGN flip_flop ( d, clk : INPUT; q : OUTPUT;) VARIABLE temp :DFF; BEGIN temp.D = d; temp.CLK = clk; Q= temp.q; END; 方法1 直接代换 SUBDESIGN flip_flop ( d, clk : INPUT; q : OUTPUT;) BEGIN 默认 声明一个D触发器 q = DFF(d,clk, ,); END; Q<=DFF(d, clk, CLRN, PRN) Q<=DFF(d, CLK, CLRN, PRN) Q<=DFF(d, clk, CLRN, PRN) Q<=DFF(D, CLK, CLRN, PRN) 成员赋值
109
更详细… 函数成员引用的意义 temp SUBDESIGN flip_flop ( d, clk : INPUT; q : OUTPUT;)
PRN CLRN INPUT OUTPUT d temp.q VARIABLE temp :DFF; INPUT clk temp BEGIN temp.D = d; temp.CLK = clk; Q= temp.q; END;
110
功能表 FUNCTION DFF (D, CLK, CLRN, PRN) RETURNS (Q); Inputs | Output
PRN CLRN CLK D | Q L H X X | H H L X X | L L L X X | Illegal H H L | L H H H | H H H L X | Qo* H H H X | Qo D CLK Q PRN CLRN
111
D触发器及使能端、清零端和置位端 D Q D Q D Q D Q D Q D Q SUBDESIGN flip_flop_enable
( clock, data : INPUT; enable, preset, clear : INPUT; qout : OUTPUT; ) VARIABLE temp : DFFE; BEGIN qout = temp.Q; temp.D = data; temp.CLK = clock; temp.CLRN= clear; temp.PRN = preset; temp.ENA= enable; END; D CLK Q PRN CLRN ENA D CLK Q PRN CLRN ENA D CLK Q PRN CLRN ENA D CLK Q PRN CLRN ENA D CLK Q PRN CLRN ENA D CLK Q PRN CLRN ENA
112
功能表 FUNCTION DFFE (D, CLK, CLRN, PRN, ENA) RETURNS (Q);
Inputs | Output CLRN PRN ENA D CLK | Q L H X X X | L H L X X X | H L L X X X | Illegal H H L X X | Qo* H H H L | L H H H H | H H H X X L | Qo* D CLK Q PRN CLRN ENA
113
有关寄存器更多... 寄存器组如何操作 其他种类的寄存器如何操作 DFFE (DFF 带使能) TFF/TFFE JKFF/JKFFE
SRFF/SRFFE
114
寄存器组声明 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; 寄存器组声明 D CLK Q PRN CLRN ENA
115
寄存器组声明的意义 SUBDESIGN bur_reg ( clk, load, d[7..0] : INPUT;
q[7..0] : OUTPUT; ) VARIABLE ff[7..0] : DFF; BEGIN ff[].CLK = clk; ff[].D = d[]; q[] = ff[].Q; END; ff[0].CLK = clk; ff[1].CLK = clk; ff[2].CLK = clk; ff[3].CLK = clk; ff[4].CLK = clk; ff[5].CLK = clk; ff[6].CLK = clk; ff[7].CLK = clk; ff[0].D = d[0]; ff[1].D = d[1]; ff[2].D = d[2]; ff[3].D = d[3]; ff[4].D = d[4]; ff[5].D = d[5]; ff[6].D = d[6]; ff[7].D = d[7]; q[0] = ff[0].Q; q[1] = ff[1].Q; q[2] = ff[2].Q; q[3] = ff[3].Q; q[4] = ff[4].Q; q[5] = ff[5].Q; q[6] = ff[6].Q; q[7] = ff[7].Q;
116
其他类型的触发器
117
FUNCTION JKFFE (J, K, CLK, CLRN, PRN, ENA) RETURNS (Q);
Inputs | Output ENA PRN CLRN CLK J K | Q X L H X X X | H X H L X X X | L X L L X X X | Illegal X H H L X X | Qo* H H H L L | Qo* H H H H L | H H H H L H | L H H H H H | Toggle L H H X X X | Qo* J CLK Q PRN CLRN ENA K
118
FUNCTION JKFF (J, K, CLK, CLRN, PRN) RETURNS (Q);
Inputs | Output PRN CLRN CLK J K | Q L H X X X | H H L X X X | L L L X X X | Illegal H H L X X | Qo* H H L L | Qo* H H H L | H H H L H | L H H H H | Toggle J CLK Q PRN CLRN K
119
FUNCTION TFFE (T, CLK, CLRN, PRN, ENA) RETURNS (Q);
Inputs | Output CLRN PRN ENA T CLK | Q L H X X X | L H L X X X | H L L X X X | Illegal H H L X X | Qo* H H H L | Qo* H H H H | Toggle H H X X L | Qo* T CLK Q PRN CLRN ENA
120
FUNCTION TFF (T, CLK, CLRN, PRN) RETURNS (Q);
Inputs | Output PRN CLRN CLK T | Q L H X X | H H L X X | L L L X X | Illegal H H L | Qo* H H H | Toggle H H L X | Qo* T CLK Q PRN CLRN
121
FUNCTION SRFFE (S, R, CLK, CLRN, PRN, ENA) RETURNS (Q);
Inputs | Output ENA PRN CLRN CLK S R | Q X L H X X X | H X H L X X X | L X L L X X X | Illegal X H H L X X | Qo* H H H L L | Qo* H H H H L | H H H H L H | L H H H H H | Toggle L H H X X X | Qo* R CLK Q PRN CLRN ENA S
122
FUNCTION SRFF (S, R, CLK, CLRN, PRN) RETURNS (Q);
Inputs | Output PRN CLRN CLK S R | Q L H X X X | H H L X X X | L L L X X X | Illegal H H L X X | Qo* H H L L | Qo* H H H L | H H H L H | L H H H H | Toggle R CLK Q PRN CLRN S
123
带寄存器的输出声明 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;
124
LPM——参数模块化函数[略]
125
FUNCTION lpm_dff (data[LPM_WIDTH-1
FUNCTION lpm_dff (data[LPM_WIDTH-1..0], clock, enable, shiftin, shiften, sclr, sset, sconst, aclr, aset, aconst) WITH (LPM_WIDTH, LPM_AVALUE, LPM_SVALUE) RETURNS (q[LPM_WIDTH-1..0], shiftout); FUNCTION lpm_ff (data[LPM_WIDTH-1..0], clock, enable, sclr, sset, sload, aclr, aset, aload) WITH (LPM_WIDTH, LPM_AVALUE, LPM_SVALUE, LPM_FFTYPE) RETURNS (q[LPM_WIDTH-1..0]);
126
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;
127
怎样使用 Help 菜单 问 : 不知到 Altera DFF/JKFFE等定义, 该怎么办 ?
答 : Altera Help 菜单是寻找相关信息的好地方。 问 : 如何使用 Help 菜单? 答 : 容易且有趣。 DFFE
128
如何使用 Help 菜单
129
寄存器的应用 三态总线的综合
130
Tri-state 三态缓存器引用 电路图形 FUNCTION TRI (in, oe) RETURNS (out); AHDL原形函数
方法2 先声明,后成员赋值 SUBDESIGN tri_state ( a, enable : INPUT; b : OUTPUT;) VARIABLE temp : TRI; BEGIN temp.in = a; temp.oe = enable; b = temp.out; END; 方法1 直接代换 SUBDESIGN tri_state (a, enable : INPUT; b : OUTPUT;) BEGIN 声明 b = TRI(a,enable); END; out<=TRI(a, oe) out<=TRI(a, enable) out<=TRI(in, oe) 成员赋值
131
更详细… 函数成员引用的意义 SUBDESIGN tri_state ( a, enable : INPUT; b : OUTPUT;)
VARIABLE temp : TRI; in out oe enable a b BEGIN temp.in = a; temp.oe = enable; b = temp.out; END;
132
TRI 三态原形 AHDL原形函数 FUNCTION TRI (in, oe) RETURNS (out); VHDL 元件声明
COMPONENT TRI PORT (a_in : IN STD_LOGIC; oe: IN STD_LOGIC; a_out: OUT STD_LOGIC); END COMPONENT; 功能表 Inputs | Output IN OE | OUT X 0 | Z 1 1 | 1 0 1 | 0 oe in out Graphic
133
OPNDRN – 漏极开路缓存器引用 电路图形 FUNCTION OPNDRN (in) RETURNS (out); AHDL原形函数
方法2 先声明,后成员赋值 SUBDESIGN opn_drn ( enable : INPUT; b : OUTPUT;) VARIABLE temp : OPNDRN; BEGIN temp.in = enable; b = temp.out; END; 方法1 直接代换 SUBDESIGN opn_drn ( enable : INPUT; b : OUTPUT;) BEGIN 声明 b = OPNDRN(enable); END; out<= OPNDRN(in) out<= OPNDRN(enable) 成员赋值
134
OPNDRN的功能 Z态 “0” “1” OPNDRN 从不输出高。怎样才能高?? 解决方案:外设置上拉电阻,在高阻的情况下将输出拉高。
135
更详细… 函数成员引用的意义 SUBDESIGN opn_drn ( enable : INPUT; b : OUTPUT;)
VARIABLE temp : OPNDRN; in out b BEGIN temp.in = enable ; enable b = temp.out; END;
136
OPNDRN原形 AHDL原形函数 FUNCTION OPNDRN (in) RETURNS (out); VHDL 元件声明
COMPONENT OPNDRN PORT (a_in : IN STD_LOGIC; a_out: OUT STD_LOGIC); END COMPONENT; 功能表 Inputs | Output IN | OUT 1 | Z 0 | 0 Graphic in out
137
使用三态缓冲器须仔细 功能表 Inputs | Output IN OE | OUT X 0 | Z 1 1 | 1 0 1 | 0
SUBDESIGN tri_state ( enable : INPUT; b : OUTPUT; ) VARIABLE temp : TRI; BEGIN temp.oe = enable; temp.in = VCC; b = temp.out; END; 功能表 Inputs | Output IN OE | OUT X 0 | Z 1 1 | 1 0 1 | 0
138
发生了什么 !!!! 得到了一个 OPNDRN 而非 TRI Max+Plus II哪错了? SUBDESIGN tri_state
( enable : INPUT; b : OUTPUT; ) VARIABLE temp : TRI; BEGIN temp.oe = enable; temp.in = GND; b = temp.out; END; 发生了什么 !!!! 得到了一个 OPNDRN 而非 TRI Max+Plus II哪错了?
139
OPNDRN 与 TRI 比较 功能是相同的 TRI (in, oe) RETURNS (out)
oe = ?? in = out oe = ?? out = Z OPNDRN (in) RETURNS (out) in = ?? out = Z in = ?? out = ? 功能是相同的 TRI : in = GND oe = enable (1) out = GND oe = enable (0) out = Z OPNDRN : in = !enable (!0) out = Z in = !enable (!1) out = GND
140
将 Tri-State 改为 OPNDRN 点击这一选项 On/Off
141
Tri-State 和 OPNDRN TRI(gnd, enable)
如果要保留 TRI-State buffer, 点击off “ Automatic Open-drain pin”选项。 如果想将 TRI-State buffer 变为 OPEN-DRAIN,点击on “ Automatic Open-drain pin”选项。 off in out oe enable b gnd in out oe enable b gnd on in out !enable b
142
使用 AHDL与 Schematic一样容易 但 使用 AHDL 更强大。
143
三态总线综合 SUBDESIGN tri_bus ( in[3..1], oe[3..1] : INPUT; out1 : OUTPUT;
) VARIABLE tnode : TRI_STATE_NODE; BEGIN tnode = TRI(in1, oe1); tnode = TRI(in2, oe2); tnode = TRI(in3, oe3); out1 = tnode; END; Graphic tnode in3 in2 in1 oe1 oe2 oe3 out1
144
双向引脚综合 Graphic SUBDESIGN bus_reg3 ( clk : INPUT; oe : INPUT;
io : BIDIR; ) VARIABLE my_dff : DFF; my_tri : TRI; BEGIN my_dff.d = io; my_dff.clk = clk; my_tri.in = my_dff.q; my_tri.oe = oe; io = my_tri.out; END; D CLK Q PRN CLRN IO OE BIDIR SUBDESIGN bus_reg2 ( clk : INPUT; oe : INPUT; io : BIDIR; ) VARIABLE dff_out : NODE; BEGIN dff_out = DFF(io, clk, ,); io = TRI(dff_out, oe); END; oe clk io OE bus_reg2 CLK IO
145
FUNCTION bus_reg2 (clk, oe) RETURNS (io);
SUBDESIGN bidir1 ( clk, oe : INPUT; io[3..0] : BIDIR; ) BEGIN io0 = bus_reg2(clk, oe); io1 = bus_reg2(clk, oe); io2 = bus_reg2(clk, oe); io3 = bus_reg2(clk, oe); END; oe clk io OE bus_reg2 CLK IO1 Graphic oe clk io OE bus_reg2 CLK IO2 oe clk io OE bus_reg2 CLK IO3
146
内部Tri-state 被Max+Plus II
oe1 in1 oe2 in2 in3 out AHDL SUBDESIGN tri_state_bus ( in1, in2, in3 : INPUT; oe1, oe2 : INPUT; out : OUTPUT;) VARIABLE tnode : TRI_STATE_NODE; BEGIN tnode = TRI(in1, oe1); tnode = TRI(in2, oe2); out = in3 & tnode; END; tnode -- Node name is 'out' from file "tri_state_bus.tdf" line 10, column 1 out = _LC1_B1; ~33~2 = LCELL( _EQ001); _EQ001 = !oe1 # in1; _LC1_B1 = LCELL( _EQ002); _EQ002 = in3 & !oe2 & ~33~2 # in2 & in3 & ~33~2; 编译结果 节点在内部 内部Tri-state 被Max+Plus II 自动转化为多路选择器 MUX out=in3&(!oe1#in1)&(!oe2#in2)
147
I/O Tri-State 总线 AHDL oe1 in1 out oe2 in2 I/O 管脚支持真Tri-State TRI tnode
SUBDESIGN tri_state_bus ( in1, in2, in3 : INPUT; oe1, oe2 : INPUT; out : OUTPUT;) VARIABLE tnode : TRI_STATE_NODE; BEGIN tnode = TRI(in1, oe1); tnode = TRI(in2, oe2); out = tnode; END; tnode I/O 管脚支持真Tri-State
148
逻辑与(AND)
149
寄存器的应用 设计计数器
150
设计计数器 SUBDESIGN 8bits (clk : INPUT; q[7..0] : OUTPUT; ) VARIABLE
temp[7..0] : DFF; BEGIN temp[].CLK = clk; temp[].D = temp[].Q +1; q[] = temp[].Q; END;
151
Creating Counters 设计计数器 SUBDESIGN ahdlcnt (
clk, load, ena, clr, d[15..0] : INPUT; q[15..0] : OUTPUT; ) VARIABLE count[15..0] : DFF; BEGIN 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; Creating Counters 设计计数器
152
clk q0 clr T CLK Q PRN CLRN ena q15 q1 load d0 d1 d15
153
INCLUDE "lpm_counter.inc";
SUBDESIGN lpm_cnt ( clk, load, ena, clr, d[15..0] : INPUT; q[15..0] : OUTPUT; ) VARIABLE my_cntr: lpm_counter WITH (LPM_WIDTH=16); BEGIN my_cntr.clock = clk; my_cntr.aload = load; my_cntr.cnt_en = ena; my_cntr.aclr = clr; my_cntr.data[] = d[]; q[] = my_cntr.q[]; END;
154
FUNCTION lpm_counter (data[LPM_WIDTH-1
FUNCTION lpm_counter (data[LPM_WIDTH-1..0], clock, clk_en, cnt_en, updown, cin, aclr, aset, aconst, aload, sclr, sset, sconst, sload) WITH (LPM_WIDTH, LPM_DIRECTION, LPM_MODULUS, LPM_AVALUE, LPM_SVALUE, CARRY_CNT_EN, LABWIDE_SCLR) RETURNS (q[LPM_WIDTH-1..0], cout, eq[15..0])
155
时序逻辑
156
状态机声明 可以这样创建一个状态机,通过在Variable Section中声明一个状态机名,它的状态,以及附加的状态位。 以下为状态机声明的范例: VARIABLE ss :MACHINE OF BITS (q1, q2, q3) WITH STATES ( s1 = B"000", s2 = B"010", s3 = B"111"); 状态位名 状态机名 状态分配值 状态名
157
<number of states> <= 2^<number of state bits>
状态机名是一个符号名。在上例中,状态机名是 ss。 在状态机名后紧跟一个冒号 “:” 及关键字 MACHINE。 状态机声明必须包括一个状态列表,可以包含一个状态位名列表。 附加的状态位用关键字OF BITS 定义,随后是以逗号分隔的符号名列表,列表必须以括号“()”括起。上例中定义的状态位是q1, q2, 及 q3。 状态用关键字WITH STATES定义,随后是以逗号分隔的符号名列表,列表必须以括号“()”括起。上例中定义的状态是s1, s2, 及 s3。 列在WITH STATES子句中的第一个状态是状态机的起始(复位)状态 。 状态名或许还会被安排一个附加值,用等号“=”和其后的数字表示。上例中s1 被安排为 B“000”, s2被安排为 B“010”, 及 s3被安排为 B “ 111 ” 。 还可以用一个状态机别名声明来对一个状态机安排一个替用名,该状态机可能在当前文档中被声明,或引用别的文档。状态机声明以分号“;”结束。 状态机的每一个状态以触发器组输出信号高低组成的某一图案唯一确定。状态位就是状态机用来储存状态的触发器输出。在一个状态机中,状态数和状态位数有以下关系: <number of states> <= 2^<number of state bits>
158
状态机初步 jump=0 s0 q=0 状态转换图 jump=1 jump=1 s1 q=1 jump=0
159
状态机初步 q jump clk reset CASE ss IS WHEN s0 => q = GND; IF jump THEN
ss = s1; END IF; WHEN s1 => q = VCC; ss = s0; END CASE; END; SUBDESIGN simple ( clk, reset, jump : INPUT; q : OUTPUT; ) VARIABLE ss: MACHINE WITH STATES (s0, s1); BEGIN ss.clk = clk; ss.reset = reset; 注意 : 所有的状态机变量都关联此时钟 T CLK Q PRN CLRN jump clk VCC q reset
160
IF (jump) THEN ss = s1; END IF; IF (jump) THEN ss = s0; END IF;
161
复位- 高有效还是低有效? ss : MACHINE WITH STATES (S0,S1) 高有效
162
分配状态机比特位和值 一个状态位就是就是一个触发器的输出,该触发器被状态机用于储存状态的一位值。 在大多数情况下,应该允许MAX+PLUS II编译器分配状态位和值以便最小化所需的逻辑资源:逻辑综合器自动最小化所需的状态位数,同时优化器件的可利用性和性能。 然而,有些状态机用超过最小状态位数的状态值可能运行更快。此外,可能要求状态机输出直接就是状态位。为了控制这些情况,在状态机声明中,可以人为确定状态位和值。
163
状态机更进一步 BEGIN ss.clk = clk; ss.reset = reset; TABLE
IF(reset) THEN ss = s2; END IF; phase[] = temp[]; TABLE ss, ccw, cw => ss; s0, 1, x => s3; s0, x, => s1; s1, 1, x => s0; s1, x, => s2; s2, 1, x => s1; s2, x, => s3; s3, 1, x => s2; s3, x, => s0; END TABLE; END; SUBDESIGN stepper ( clk, reset : INPUT; ccw, cw : INPUT; phase[3..0] : OUTPUT; ) VARIABLE ss: MACHINE OF BITS (temp[3..0]) WITH STATES ( s0 = B"0001", s1 = B"0010", s2 = B"0100", s3 = B"1000"); 注意: 不需要声明 temp的属性 自动声明为 DFF。
164
用户可以控制状态 Bit
165
具有同步输出的状态机 Moore型 !y !y y s0 !y y s1 1 s2 1 !y y y s3
166
具有同步输出的状态机 BEGIN ss.clk = clk; ss.reset = reset; TABLE
% current current next % % state input state % ss, y => ss; s0, => s0; s0, => s2; s1, => s0; s1, => s2; s2, => s2; s2, => s3; s3, => s3; s3, => s1; END TABLE; END; SUBDESIGN moore1 ( 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 = );
167
D CLK Q PRN CLRN y clk z reset
168
SUBDESIGN moore2 ( 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, => s0, ; s0, => s2, ; s1, => s0, ; s1, => s2, ; s2, => s2, ; s2, => s3, ; s3, => s3, ; s3, => s1, ; END TABLE; END;
169
Mealy型 s0 s3 s1 s2 In=0 out=0 In=1 out=1 In=1 out=1 In=0 out=0 In=0
170
SUBDESIGN mealy ( clk : INPUT; reset : INPUT; y : INPUT; z : OUTPUT; ) 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, s0; s0, => 1, s1; s1, => 1, s1; s1, => 0, s2; s2, => 0, s2; s2, => 1, s3; s3, => 0, s3; s3, => 1, s0; END TABLE; END;
171
D CLK Q PRN CLRN y clk z reset
172
带有状态恢复的状态机
173
例: ok = (sequence == four); BEGIN sequence.clk = clk;
SUBDESIGN recover ( clk : INPUT; go : INPUT; ok : OUTPUT; ) VARIABLE sequence : MACHINE OF BITS (q[2..0]) WITH STATES ( idle, one, 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; END CASE; ok = (sequence == four); END;
174
状态机卡在 FOUR
175
非法状态的恢复 ok = (sequence == four); 3个 bits 有8个状态 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 => sequence = idle; END CASE; ok = (sequence == four); END; SUBDESIGN recover ( clk : INPUT; go : INPUT; ok : OUTPUT; ) VARIABLE sequence : MACHINE OF BITS (q[2..0]) WITH STATES ( idle, one, two, three, four, illegal1, illegal2, illegal3); 3个 bits 有8个状态 只有5个状态是有用的。 使用这些 RECOVER 项最好
176
RECOVER
177
状态机的输入和输出
178
定义一个状态机具有状态 : S1, S2, S3, S4, S5 SUBDESIGN ss_def
(clk, reset, count : INPUT; ss_out : MACHINE OUTPUT; ) VARIABLE ss: MACHINE WITH STATES (s1, s2, s3, s4, s5); BEGIN ss_out = ss; CASE ss IS WHEN s1=> IF count THEN ss = s2; ELSE ss = s1; END IF; WHEN s2=> IF count THEN ss = s3; ELSE ss = s2; END IF; WHEN s3=> IF count THEN ss = s4; ELSE ss = s3; END IF; WHEN s4=> IF count THEN ss = s5; ELSE ss = s4; END IF; WHEN s5=> IF count THEN ss = s1; ELSE ss = s5; END IF; END CASE; ss.(clk, reset) = (clk, reset); END;
179
(ss_in : MACHINE INPUT; out : OUTPUT; ) BEGIN
SUBDESIGN ss_use (ss_in : MACHINE INPUT; out : OUTPUT; ) BEGIN out = (ss_in == s2) OR (ss_in == s4); END; 状态机: 再此定义,在别处使用
180
FUNCTION ss_def (clk, reset, count) RETURNS (MACHINE ss_out);
FUNCTION ss_use (MACHINE ss_in) RETURNS (out); SUBDESIGN top1 ( sys_clk, /reset, hold : INPUT; sync_out : OUTPUT; ) VARIABLE ss_ref: MACHINE; % Machine Alias Declaration % BEGIN ss_ref = ss_def(sys_clk, !/reset, !hold); sync_out = ss_use(ss_ref); END;
181
状态机输入输出 状态机别名 状态机在此使用 状态机定义在此 ss_def SS_REF ss_use sys_clk sync_out
RESET COUNT SS_OUT SS_REF SS_IN OUT ss_use sys_clk sync_out reset hold 状态机别名 状态机在此使用 状态机定义在此
182
FUNCTION ss_def (clk, reset, count) RETURNS (MACHINE ss_out);
FUNCTION ss_use (MACHINE ss_in) RETURNS (out); SUBDESIGN top2 ( sys_clk, /reset, hold : INPUT; sync_out : OUTPUT; ) VARIABLE sm_macro : ss_def; sync : ss_use; BEGIN sm_macro.(clk, reset, count) = (sys_clk, !/reset, !hold); sync.ss_in = sm_macro.ss_out; sync_out = sync.out; END;
183
AHDL 支持层次设计 层次设计 子模块设计 易于管理和理解 可利用已完善并验证的设计成果
184
例 1 : div2 subtop 4count count SUBTOP 7segment CLK2 CLK OUT[6..0]
LDN A B C D CIN DNUP SETN CLRN CLK clk QA QB QC QD COUT i0 i1 i2 i3 i[3..0] SUBTOP E F G I[3..0] a b c d e f g 7segment
185
SUBDESIGN div2 ( clk2 : INPUT; clk : OUTPUT; ) VARIABLE temp : DFF; BEGIN temp.clk = clk2; temp.d = !(temp.q); clk = temp.q; END;
186
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; END;
187
INCLUDE “7segment.inc” INCLUDE “4count” SUBDESIGN subtop ( clk : INPUT; out[6..0] : OUTPUT; ) VARIABLE temp : 7segment; temp1 : 4count; BEGIN temp1.clk = clk; temp.i[] = temp1.(qd,qc,qb,qa); out[] = temp.(a,b,c,d,e,f,g); END;
188
什么是 INC 文件 INC 提供接口信息 INC 文件实例 FUNCTION 7segment (i[3..0])
RETURNS (a, b, c, d, e, f, g); FUNCTION div2 (clk2) RETURNS (clk); 这个函数输入矢量为 i[3..0] 输出端子名为 a,b,c,d,e,f,g
189
INCLUDE“subtop.inc” INCLUDE “div2 ” SUBDESIGN top ( clk50 : INPUT; segment[6..0] : OUTPUT; ) VARIABLE temp : subtop; temp1 : div2; BEGIN temp1.clk2 = clk50; temp.clk = temp1.clk; Segment[ ] = temp.out[ ]; END;
190
仿真结果 a g d a g d a g d a g d a g d a g d a g d a g d a g d a g d a g d
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; a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e a b f g d c e
191
INCLUDE "ss_use.inc"; INCLUDE "ss_def.inc"; SUBDESIGN top1 (sys_clk, reset, hold : INPUT; sync_out : OUTPUT; ) VARIABLE ss_ref: MACHINE; BEGIN ss_ref = ss_def(sys_clk, reset, hold); sync_out = ss_use(ss_ref); END;
192
AHDL进阶 欲用必知
193
使用 Altera 提供的函数 Altera 提供 Old-Style 宏函数 何处获得 ? 怎样使用 ? 74xx
MAXPLUS2\MAX2LIB\MF 怎样使用 ?
194
怎样使用 7400 INCLUDE 7400; SUBDESIGN mf1 ( a, b : INPUT; c : OUTPUT;)
VARIABLE temp : 7400; BEGIN temp.2 = a; temp.3 = b; c = temp.1; END;
195
怎样使用 4COUNT INCLUDE “4count.inc” SUBDESIGN prim1 ( clk : INPUT;
out[3..0] : OUTPUT;) VARIABLE temp : 4count; BEGIN temp.clk = clk; out0 = temp.qa; out1 = temp.qb; out2 = temp.qc; out3 = temp.qd; END;
196
使用 Altera 提供的LPM 库安装在 - MAXPLUS2\MAX2LIB\MEGA_LPM
如何使用 LPM_ADD_SUB、LPM_RAM/ LPM_FIFO 等如何使用
197
例: 使用 LPM_MULT Help 菜单提供在AHDL中如何使用 LPM 有关信息
198
INCLUDE "lpm_mult. inc"; SUBDESIGN lpm_mult1 ( a[3. 0], b[3
INCLUDE "lpm_mult.inc"; SUBDESIGN lpm_mult1 ( a[3..0], b[3..0] : INPUT; c[7..0] : OUTPUT; ) VARIABLE temp : lpm_mult with (LPM_WIDTHA = 4, LPM_WIDTHB = 4, LPM_WIDTHP = 8, LPM_WIDTHS = 1); BEGIN temp.dataa[]=a[]; temp.datab[]=b[]; c[]=temp.result[]; END;
199
例 : 使用 LPM_RAM_DQ
200
试一试 INCLUDE “lpm_ram_dq.inc” SUBDESIGN lpmram
( address[7..0], we, data[7..0] :INPUT; dataout[7..0] : OUTPUT; ) VARIABLE temp : lpm_ram_dq with (LPM_WIDTH = 8, LPM_WIDTHAD = 8, LPM_INDATA = 揢NREGISTERED? LPM_ADDRESS_CONTROL = 揢NREGISTERED? LPM_OUTDATA = 揢NREGISTERED? EAB = 揙N); BEGIN temp.address[] = address[]; temp.data[] = data[]; temp.we = we; dataout[] = temp.q[]; END;
201
AHDL进阶 或可有助
202
什么是 Parameter 使用 Parameter, 设计很容易调试。 Parameter值 在编译阶段提供,而不是在设计阶段。
203
Parameter 实例 需要 8个 DFF 需要 8个 DFF 此值在设计阶段提供 此值在编译阶段提供 在编译阶段怎样赋值?
SUBDESIGN flip_flop ( clk, d[7..0] : INPUT; q[7..0] : OUTPUT; ) VARIABLE temp[7..0] : DFF; BEGIN temp[].d = d[]; temp[].clk = clk; q = temp[].q; END; SUBDESIGN flip_flop ( clk, d[length..0] : INPUT; q[length..0] : OUTPUT; ) VARIABLE temp[lenght..0] : dff; BEGIN temp[].d = d[]; temp[].clk = clk; q = temp[].q; END; 需要 8个 DFF 需要 8个 DFF 此值在设计阶段提供 此值在编译阶段提供 在编译阶段怎样赋值?
204
Parameter 在编译过程中传递 修改一处, 自动更新其余 PARAMETERS ( length );
SUBDESIGN flip_flop ( clk, d[length..0] : INPUT; q[length..0] : OUTPUT; ) VARIABLE temp[length..0] : DFF; BEGIN temp[].d = d[]; temp[].clk = clk; q[] = temp[].q; END; 修改一处, 自动更新其余
205
Parameter进一步 缺省值 PARAMETERS ( length = 5 );
SUBDESIGN flip_flop ( clk, d[length..0] : INPUT; q[length..0] : OUTPUT; ) VARIABLE temp[length..0] : DFF; BEGIN temp[].d = d[]; temp[].clk = clk; q[] = temp[].q; END; 缺省值 Parameter value assignment : if (parameter provide through the Global parameter option) then use the Global parameter option else if (default value is provided) then use the default value ERROR : missing parameter value end if
206
创建自己的 LPM 参数化符号 PARAMETERS ( length = 5 ); SUBDESIGN flip_flop
( clk, d[length..0] : INPUT; q[length..0] : OUTPUT; ) VARIABLE temp[length..0] : DFF; BEGIN temp[].d = d[]; temp[].clk = clk; q[] = temp[].q; END; 参数化符号
207
旧的 Schematic设计如何沿用??? 问: 旧的 Schematic 设计, 在 AHDL如何沿用 ? 答: 改为AHDL设计。
问: 但设计很大且无BUG, 又不想冒险,如何处理? 答: Altera 提供AHDL与Schematic设计的接口。 问: 需要做什么,能否保证100%正确 ? 答: 不需做任何事情 Max+Plus II 保证 100% 正确。
208
解决方案 首先创建 INC 文件 如何做 ? D Q 25MHz INCLUDE "test1.inc";
INCLUDE "4count"; SUBDESIGN advan ( clk50 : INPUT; ca[3..0] : OUTPUT; cb[3..0] : OUTPUT; ) VARIABLE temp : test1; tempa : 4count; tempb : 4count; BEGIN temp.50mhz = clk50; tempa.clk = clk50; tempb.clk = temp.25mhz; ca[] = tempa.(qd, qc, qb, qa); cb[] = tempb.(qd, qc, qb, qa); END; D CLK Q PRN CLRN 50MHz 25MHz
209
仿真结果 50MHz 25MHz
210
AHDL 格式总结 Title Statement Parameters Statement Include Statement
TITLE “display Controller use EPM7032LC44-7 ” Parameters Statement PARAMETERS ( width, numwords = 8); Include Statement INCLUDE “8count” Constant Statement CONSTANT address_decode = H “78” Define Statement DEFINE MAX(a,b) = (a > b) ? a : b; AHDL 格式总结 Subdesign Section SUBDESIGN project_name ( a[width..0] : INPUT; b[numwords..0] : OUTPUT;) Variable Section VARIABLE temp : DFF; temp1 : TRI_STATE_NODE; temp3 : MACHINE; Logic Section BEGIN DEFAULTS a[]= VCC; END DEFAULTS IF ( ) THEN END IF; END;
211
Logic Section - Defaults Statement - Assert Statement - Boolean Equations - Boolean Control Equations - Case Statement - For Generate Statement - If Then Statement - If Generate Statement - In-Line Logic Function Reference - Truth Table Statement Title Statement Include Statement Constant Statement Define Statement Parameters Statement Function Prototype Statement Options Statement Assert Statement Subdesign Section Variable Section - Instance Declaration - Node Declaration - Register Declaration - State Machine Declaration - Machine Alias Declaration
212
Altera TDO 和 ACO 文件 是什么?
213
当在 Max+Plus II v8.0下做的工程, 换为v9.x后怎么办 ?
ss_def CLK RESET COUNT SS_OUT SS_REF SS_IN OUT ss_use sys_clk sync_out reset hold 当在 Max+Plus II v8.0下做的工程, 换为v9.x后怎么办 ? 使用 TDO 和ACO 文件保持在 Max+Plus II vx.x下的设计
214
选项在何处
215
什么是 TDO 文件 TDO 文件实例 最底层的逻辑单元
216
什么是 ACO 文件 ACO 文件实例 Pin/LC 定位信息
217
TDO和ACO 文件的用处 Max+Plus II 的不同版本会造成不同的逻辑综合和试配算法, 将引起
不同数量的 Logic Element/Macro Cell 的使用 不同的时间延迟和不同的执行结果 TDO文件是原设计的最底层逻辑单元的转换文件 ACO 包含所有Logic Cell/Pin 的定位信息
218
小心使用 TDO 和ACO 不要忘记 将 TDO 改名为 TDF 将 ACO改名为 ACF 将全局工程逻辑综合改为 WYSIWYG
(What you see is what you get) WYSIWYG 将不做任何逻辑综合和优化 .... 这就是所要达到的目的 – 不做任何改变. OK!
219
总 结 使用AHDL 与图形一样容易但更强大。 尽量使用Altera提供的LPM 而不是用你自己创建的。 层次设计方法 缩短设计周期
总 结 使用AHDL 与图形一样容易但更强大。 尽量使用Altera提供的LPM 而不是用你自己创建的。 缩短设计周期 易于适配 Altera 器件 少用 Logical Cell /Macro Cell usually higher in performance 层次设计方法 易于管理 易于应用 ASSIGN OPTION
220
秘诀 : TMYUTMUK T M Y U K he ore ou se now
Similar presentations