Download presentation
Presentation is loading. Please wait.
Published byΗμέρα Ελευθεριάδης Modified 5年之前
1
Danny Mok Altera HK FAE (dmok@altera.com)
AHDL培训教材 Danny Mok Altera HK FAE 2018/12/ P.1
2
什么是 AHDL? AHDL是Altera Hardware Description Language的缩写 由 Altera公司开发
集成在 Altera的开发软件Max+Plus II中 以语言的形式而不是图形的形式描述硬件 容易修改 容易维护 尤其适合实现以下的逻辑功能 复杂的组合逻辑 BCD码向 7段字形的转换器 状态机 地址译码 其他你还没想到的功能…….. 2018/12/ P.2
3
接上页 与图形输入方式一样容易 功能与其他硬件描述语言( HDL)同样强大 如:标准VHDL、 Verilog HDL 等
2018/12/ P.3
4
怎样使用 ADHL? 使用任何一个文本编辑器创建设计文件 点击这 个按钮
Altera的开发软件Max+Plus II 也提供了一个文本编辑器 输入你的 AHDL设计文件 点击这 个按钮 2018/12/ P.4
5
接上页 创建 AHDL文件 2018/12/ P.5
6
接上页 把你的 ADHL保存为 name.TDF的形式 两者必 须相同 2018/12/ P.6
7
接上页 点击这 个图标 2018/12/ P.7
8
编译过程中的错误定位 错误定位容易 点击错 误消息 点击定位按钮 错误 定位 2018/12/ P.8
9
AHDL模板 If-then-else case-end case loop-end loop 忘了怎么办? ??…??? 修改代码
10
一般的AHDL文件格式 关键字 SUBDESIGN decode1 ( 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端口 逻辑表达式 AHDL格式 2018/12/ P.10
11
第一个 AHDL设计-地址译码器 SUBDESIGN decode1 ( a[3..0] : input;
Chip_enable = a0 & a1 & a2 & !a3 SUBDESIGN decode1 ( a[3..0] : input; chip_enable : output; ) begin chip_enable = (a[3..0] == H"7"); end; 2018/12/ P.11
12
为什么使用 AHDL 而不用图形输入方式 容易修改 输入代码和证实逻辑同时进行 将译码输出条件由H”7” 改为H”A”
SUBDESIGN decode1 ( a[3..0] : input; chip_enable : output; ) begin chip_enable = (a[3..0] == H"A"); end; 编译器自己解释函数 只需修改一个字母 修改更麻烦 Chip_enable = !a0 & a1 & !a2 & a3 2018/12/ P.12
13
更多的优势 SUBDESIGN decode1 ( a[3..0] : input; chip_enable : output; )
begin chip_enable = (a[3..0] == B"1x0x"); end; 比较器的某些输入比特可以忽略 2018/12/ P.13
14
AHDL基本知识 “加”运算符: + “减”运算符: - 数量“相等”运算符: == “不等”运算符: != “大于”运算符: >
“大于或等于”运算符: >= “小于”运算符: < “小于或等于”运算符: <= 逻辑“或”运算符: # 逻辑“逻辑与”运算符: & 2018/12/ P.14
15
使用常数(Constant)功能 如果文件中相同的数字、字符串或者算术表达式重复出现多次,使用常数(Constant)来表示它们 优点
如果修改,只需改变一个声明 修改一处即可修 改整个设计文件 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; 在关键字 SUBDESIGN 之前,定义常数 ( CONSTANT) 2018/12/ P.15
16
常数( Constant)的其他用途 常数使用举例 定义一个常数值 定义一个算术表达式 通过预先定义的常数 定义新的常数
Constant IO_ADDRESS = H”370”; Constant FOO = 1+2*3 - LOG2(256); Constant FOO_PLUS_one = FOO + 1; 定义一个常数值 定义一个算术表达式 通过预先定义的常数 定义新的常数 2018/12/ P.16
17
组合逻辑的实现 out1 = a0 & !a1 out2 = a0 & !a1 # b AHDL设计文件
SUBSDESIGN decode1 ( a0, a1, b : input; out1, out2 : output; ) begin out1 = a0 & !a1; out2 = out1 # b; end; 图形设计文件 2018/12/ P.17
18
定义节点 图形方式 AHDL 方式 SUBDESIGN decode1 ( a0, a1, b, d: input;
out2, out3 : output; ) variable temp : node; begin temp = a0 & !a1; out2 = temp # b; out3 = temp & d; end; out2 = a0 & !a1 # b out3 = a0 & !a1 & d temp 图形方式 2018/12/ P.18
19
总线操作 功能相同 但容易描述 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; SUBDESIGN decode1 ( a[3..0], b[3..0] : input; out[3..0]: output; ) begin out1[] = a[] & b[]; end; 功能相同 但容易描述 2018/12/ P.19
20
总线操作的其他方式 总线操作 a[9..0], b[9..0] a7=b9, a6=b8, a5=b7, a4=b6
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 2018/12/ P.20
21
高级总线操作 总线 总线阵列 a[3..2][1..0] = b[]; 首先对低位比特赋值 a3_1 = b3 a3_0 = b2
b3, b2, b1, b0 (having 4 members) MSB is b3, LSB is b0 总线阵列 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 (having 12 members) MSB is a3_2, LSB is a0_0 a[3..2][1..0] = b[]; a3_1 = b a3_0 = b2 a2_1 = b a2_0 = b0 首先对低位比特赋值 2018/12/ P.21
22
真值表 i[3..0] Segment 7 0 0 1 1 2 2 F F 修改非常方便 a 2018/12/9 P.22 b f g e
F F a b c d e f g 2018/12/ P.22 修改非常方便
23
IF-THEN-ELSE语句 SUBDESIGN priority ( low, medium, high : input;
highest_level[3..0] : output; ) begin if ( high == B”1”) then highest_level[] = B”1000”; elsif (medium == B”1”) then highest_level[] = B”0100”; elsif (low == B”1”) then highest_level[] = B”0010”; else highest_level[] = B”0001”; end if; end; 2018/12/ P.23
24
需要4个逻辑单元 2018/12/ P.24
25
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; 注意这一行的用法 2018/12/ P.25
26
2018/12/ P.26
27
循环语句FOR...LOOP... 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; for i in 0 to num_of_bit generate b[num_of_bit - i] = a[i]; end generate; 实现相同的功能更加容易 (a[num_of_bit..0] : input; b[num_of_bit..0] : otuput; b[num_of_bit..0] = a[0..num_of_bit]; 2018/12/ P.27
28
用图形方式调用AHDL 使用文件菜单的“Create Default Symbol”条目为 AHDL 设计创建默认符号
在图形输入中使用这个默认符号 2018/12/ P.28
29
寄存器逻辑的实现 方法 2 方法 1 SUBDESIGN flip_flop SUBDESIGN flip_flop
( d, clk : input; q : output;) begin q = dff(d,clk, ,); end; SUBDESIGN flip_flop ( d, clk : input; q : output;) variable temp : dff; begin temp.d = d; temp.clk = clk; q = temp.q; end; 调用一个 D-Flipflop 2018/12/ P.29
30
更详细的说明 2018/12/ P.30
31
关于寄存器的其他问题 如何实现总线寄存器 其他类型的寄存器的应用 DFFE: 带使能端的D触发器
TFF/TFFE:T触发器和带使能端的T触发器 JKFF/JKFFE :JK触发器和带使能端的JK触发器 SRFF/SRFFE:SR触发器和带使能端的SR触发器 2018/12/ P.31
32
总线寄存器的实现 SUBDESIGN bus_reg ff[0].clk = clk; ( clk, 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; 2018/12/ P.32
33
带清零端、预置端和使能端的D触发器 SUBDESIGN flip_flop_enable
( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; D CLK CLRN PRN ENA Q SUBDESIGN flip_flop_enable ( clock, data, enable, preset, clear : input; qout : output; ) variable temp : dffe; begin temp.d = data; temp.clk = clock; temp.clrn = clear; temp.prn = preset; temp.ena = enable; qout = temp.q; end; PRN D Q CLK ENA CLRN 2018/12/ P.33
34
其他类型的触发器 2018/12/ P.34
35
帮助菜单的使用 问:我不知道怎样使用 Altera的D触发器和带使能端的JK触发器,我该怎么办 ?
问:怎样使用帮助菜单 ? 答: 很容易而且很有趣 DFFE 2018/12/ P.35
36
帮助菜单的使用 2018/12/ P.36
37
三态缓冲器的实现 方法 1 方法 2 SUBDESIGN tri_state (a, enable : input;
b : output;) begin b = tri(a, enable); end; ( a, enable : input; variable temp : tri; temp.in = a; temp.oe = enable; b = temp.out; 2018/12/ P.37
38
更详细的说明 2018/12/ P.38
39
OPNDRN -漏极开路缓冲器 Method 1 Method 2 SUBDESIGN tri_state
SUBDESIGN opn_drn (enable : input; b : output;) begin b = opndrn(enable); end; SUBDESIGN tri_state ( enable : input; variable temp : opndrn; temp.in= enable; b = temp.out; 2018/12/ P.39
40
更详细的说明 2018/12/ P.40
41
使用 AHDL 与使用原理图同样方便 但是 AHDL 功能更强大
2018/12/ P.41
42
练习部分 AHDL SUBDESIGN tri_io ( clk, enable : input; io : bidir;)
variable temp1 : dff; temp2 : tri; begin temp1.d = io; temp1.clk = clk; temp2.in = temp1.q; temp2.oe = enable; io = temp2.out; end; 输入引脚 双向引脚 clk, enable : input; io : bidir; 2018/12/ P.42
43
轻松地设计一个8位计数器 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; 2018/12/ P.43
44
状态机设计 状态转移图 jump=0 q = 0 S0 jump=1 S1 q = 1 SUBDESIGN simple
( clk, reset, jump : 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 (jump) then ss = s1; end if; when s1 => q = vcc; ss = s0; end case; end; 状态转移图 注 : 所有的状态机都必须受时钟驱动 S0 S1 jump=1 q = 0 q = 1 jump=0 2018/12/ P.44
45
状态转移波形图 if (jump) then ss = s1; end if; ss = s0; 2018/12/ P.45
46
状态机设计的其他问题 SUBDESIGN stepper TABLE ( reset, ccw, cw, clk : 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”); begin ss.clk = clk; 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; 注 : 不必对 TEMP进行声明 它会自动声明为D触发器 2018/12/ P.46
47
状态转移图 用户可以控制初始状态 2018/12/ P.47
48
练习题 SUBDESIGN stepper TABLE ( reset, ccw, cw, clk : 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”); begin ss.clk = clk; 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; 试着修改CASE语句的真值表 2018/12/ P.48
49
没有恢复状态的状态机 SUBDESIGN recover ( clk, 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; 状态机停留在状态“ FOUR”上面 2018/12/ P.49
50
状态机最好具有自启动功能 SUBDESIGN recover 三比特实现八个状态 ( clk, 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; when OTHERS => sequence = idle; end case; ok = (sequence == four); end; 三比特实现八个状态 只有五个状态有用时, 最好使用自启动选项 2018/12/ P.50
51
结论 合适的工具 帮助你实现成功的产品 电路规模大或者设计比较复杂时使用下列设计方法: 在优化设计或者实现高速电路时
AHDL VHDL或者Verilog HDL 在优化设计或者实现高速电路时 采用 AHDL方式、图形方式、 VHDL方式或者Verilog HDL方式混合输入 尽可能发挥工程师的聪明才智 合适的工具 帮助你实现成功的产品 2018/12/ P.51
Similar presentations