HDL、EDA和FPGA
- HDL(Hardware Description Language,硬件描述语言)
- 描述数字电路,比如Verilog
- EDA(Electronic Design Automation,电子设计自动化)
- 将HDL编译为数字电路的门级网表,比如Intel Quartus Prime Lite Edition
- FPGA(Field Programmable Gate Array,现场可编程门阵列)
- 数字电路的门级网表的物理实现,比如Intel DE10-Lite
- Intel DE10-Lite的物理资源
- 下方 –> 6个七段数码管、10个开关、10个LED
- 右侧 –> 2个按钮
- 我们需要使用有限的物理资源,实现数字电路的功能
Intel DE10-Lite
七段数码管显示十六进制数
- Verilog和物理资源
- HEX[7:0]
- 8位二进制数 –> 1个七段数码管、1个小数点
- HEX0~HEX5 –> 6个七段数码管、6个小数点
- SW[9:0]
- 10位二进制数 –> 10个开关
- LEDR[9:0]
- 10位二进制数 –> 10个LED
- KEY[1:0]
- 2位二进制数 –> 2个按钮
- HEX[7:0]
- 七段数码管
- 0~5 –> 从上方的短横开始,顺时针旋转
- 6 –> 中间的短横
- 7 –> 小数点
- 置1不显示,置0显示
_ 0
|_| 561
|_|. 432 7
- 七段数码管显示十六进制数
- Verilog的模块
- module、endmodule之间
- input –> 输入为10个开关(SW)
- output –> 输出为10个LED(LEDR)、1个七段数码管(HEX0)
- Verilog的函数
- function、endfunction之间
- num[3:0] –> 输入为4位二进制数
- digit[7:0] –> 输出为十六进制数的七段数码管表示
- 它类似于编程语言的宏,而不是函数
- Verilog的assign语句
- 右边的端口,连接到左边的端口
- 我们只使用了4个开关,即可表示1个十六进制数
- Verilog的模块
// ----- Seven-Segment Display, Hexadecimal -----
// (SW) -> (LEDR, HEX0)
module TopLevel(SW, LEDR, HEX0);
input [9:0] SW;
output [9:0] LEDR;
output [7:0] HEX0;
// (num) -> (digit)
function automatic [7:0] digit;
input [3:0] num;
case (num)
0: digit = 8'b11000000; // Display 0
1: digit = 8'b11111001; // Display 1
2: digit = 8'b10100100; // Display 2
3: digit = 8'b10110000; // Display 3
4: digit = 8'b10011001; // Display 4
5: digit = 8'b10010010; // Display 5
6: digit = 8'b10000010; // Display 6
7: digit = 8'b11111000; // Display 7
8: digit = 8'b10000000; // Display 8
9: digit = 8'b10010000; // Display 9
10: digit = 8'b10001000; // Display A
11: digit = 8'b10000011; // Display b
12: digit = 8'b11000110; // Display C
13: digit = 8'b10100001; // Display d
14: digit = 8'b10000110; // Display E
15: digit = 8'b10001110; // Display F
endcase
endfunction
assign LEDR = SW;
assign HEX0 = digit(SW[3:0]);
endmodule
Verilog的三种层级
- 全加器,3个二进制数相加,求出和(Sum)、进位(Carry)
- 门级
- 指定逻辑门,比如and、or、xor
- 数据流级
- 指定逻辑运算,比如与(&)、或(|)、异或(^)
- 行为级
- 指定行为,比如加(+)、位联结({})
- always @(…)语句
- 括号中为敏感列表,比如星号(*)表示任意信号的改变
- 当敏感列表中的事件发生时,执行语句块中的行为
- wire变量类似于编程语言的局部变量,always语句的赋值变量必须为reg变量
- 门级
// ----- Gate -----
// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
input [9:0] SW;
output [9:0] LEDR;
wire AB, AC, BC;
// Sum
xor SumSig (LEDR[0], SW[0], SW[1], SW[2]);
// Carry
and (AB, SW[0], SW[1]);
and (AC, SW[0], SW[2]);
and (BC, SW[1], SW[2]);
or CarrySig (LEDR[1], AB, AC, BC);
endmodule
// ----- Dataflow -----
// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
input [9:0] SW;
output [9:0] LEDR;
// Sum
assign LEDR[0] = SW[0] ^ SW[1] ^ SW[2];
// Carry
assign LEDR[1] = SW[0] & SW[1] | SW[0] & SW[2] | SW[1] & SW[2];
endmodule
// ----- Behavior -----
// (SW) -> (LEDR)
module TopLevel(SW, LEDR);
input [9:0] SW;
output [9:0] LEDR;
reg sum, carry;
// Sum
assign LEDR[0] = sum;
// Carry
assign LEDR[1] = carry;
always @(*)
{carry, sum} = SW[0] + SW[1] + SW[2];
endmodule