目标芯片: EP3C40Q240C8(Cyclone III) 实验系统: 康芯 GW48 系列(PK2/PK3/PK4 均适用) 适配板: GW3C40 EDA 工具: Quartus II 9.1 (32-Bit)
在进行板级烧录前,请确认以下事项:
- 所有 9 个 VHDL 源文件已添加到 Quartus II 工程中
- 顶层实体已设置回
elevator_top(仿真时可能改为了子模块) - 功能仿真已通过验证
⚠️ 重要:如果你之前仿真时把顶层实体改成了elevator_ctrl,必须先改回来!操作:Assignments → Settings... → General → 将 Top-level entity 改回
elevator_top→ OK
如果你在仿真时修改过 clk_divider.vhd 的分频常量(仿真加速用),必须改回原始值:
-- 必须是原始值(50MHz 分频)
constant CNT_1HZ_MAX : std_logic_vector(24 downto 0) := "1011111010111100000111111"; -- 24999999
constant CNT_100HZ_MAX : std_logic_vector(17 downto 0) := "111101000010001111"; -- 249999
constant CNT_500HZ_MAX : std_logic_vector(15 downto 0) := "1100001101001111"; -- 49999
constant CNT_1KHZ_MAX : std_logic_vector(14 downto 0) := "110000110100111"; -- 24999确认以下设备就绪:
| 物品 | 说明 |
|---|---|
| GW48 实验箱 | 主系统板(PK2/PK3/PK4 均可) |
| GW3C40 适配板 | 已插入实验箱的适配座上,带 EP3C40Q240C8 芯片 |
| USB 下载器 | USB-Blaster(或 ByteBlasterMV 并口下载器) |
| 10 芯 JTAG 线 | 连接下载器和适配板 JTAG 口 |
| 电源线 | 实验箱供电 |
- 点击菜单 Assignments → Settings...
- 左侧 Category 选择 Device
- 在 Family 下拉框中选择
Cyclone III - 在下方的过滤条件中设置:
- Package:
Any(或选PQFP) - Pin count:
240 - Speed grade:
8
- Package:
- 在 Available devices 列表中找到并选中
EP3C40Q240C8
💡 如果列表中找不到此型号,尝试将 Package 设为
Any,然后在列表中搜索包含3C40的型号。Quartus II 9.1 中该芯片的完整名称可能显示为EP3C40Q240C8N(带 N 后缀表示无铅封装)。
- 点击 Device & Pin Options... 按钮
- 在 General 页中:
- 默认选项通常不需要修改,保持 Auto-restart configuration after error 勾选即可
- (可选)点击 Configuration 页签:
- 如果你计划后续烧录 EPCS 配置芯片,可以在此选择配置方式为
Active Serial - 如果只做 JTAG 直接下载测试,此页不用改
- 如果你计划后续烧录 EPCS 配置芯片,可以在此选择配置方式为
- 点击 Unused Pins 页签:
- 选择 As input tri-stated with weak pull-up(未使用引脚设为三态弱上拉,最安全)
- 点击 OK 关闭 Device & Pin Options
- 点击 OK 关闭 Settings
GW48 实验箱通过"模式选择键"切换不同的电路结构连接方式。
推荐使用实验电路结构图 NO.5,原因:
- 提供 8 个独立的高低电平键(键1~键8),适合作为电梯的各种按钮输入
- 提供 8 个数码管(经外部 7 段译码器显示),可显示楼层信息
- 提供 发光管 D1~D8,可用于方向指示和状态指示
- 扬声器 SPEAKER 直连,可驱动蜂鸣器
- 在实验箱上找到"模式选择键"(标注为 "选择键" 的按钮)
- 反复按动此键,直到"模式数码显示"显示数字
5 - 切换完成后,按一下右侧的"系统复位键",使系统进入该模式
这是最关键的步骤。需要将 elevator_top 的每个端口信号映射到 EP3C40Q240C8 芯片的物理引脚上。
以下映射来自 GW48 实验箱模式 NO.5 的电路结构(GW3C40 适配板),并已写入工程引脚约束 quartus/elevator_top.qsf。
| 端口信号 | 方向 | 系统资源 | PIO 标准名 | EP3C40 引脚号 |
|---|---|---|---|---|
clk |
IN | CLOCK0(选 50MHz) | CLOCK0 | 152 |
rst_n |
IN | 键 1(高低电平) | PIO0 | 18 |
⚠️ 时钟频率选择:在实验箱上找到"CLOCK0"频率选择跳线座,将短路帽插到 50MHz 位置(因为clk_divider的分频常量是基于 50MHz 设计的)。
| 端口信号 | 功能 | 系统资源 | PIO 标准名 | EP3C40 引脚号 |
|---|---|---|---|---|
btn_up1 |
1楼上行 | 键 2 | PIO1 | 21 |
btn_up2 |
2楼上行 | 键 3 | PIO2 | 22 |
btn_dn2 |
2楼下行 | 键 4 | PIO3 | 37 |
btn_dn3 |
3楼下行 | 键 5 | PIO4 | 38 |
btn_go1 |
去1楼 | 键 6 | PIO5 | 39 |
btn_go2 |
去2楼 | 键 7 | PIO6 | 41 |
btn_go3 |
去3楼 | 键 8 | PIO7 | 43 |
💡 模式 NO.5 的 8 个键都是高低电平发生器:每按一次,输出在高/低之间切换。按键时对应的发光管会指示当前电平。
由于模式 NO.5 的 8 个键已全部用完,开关门和报警按钮使用实验箱上的电平控制开关(拨码开关):
| 端口信号 | 功能 | 系统资源 | 实验箱标号 | EP3C40 引脚号 |
|---|---|---|---|---|
btn_open |
手动开门 | 电平开关 (自定) | IO26 (PIO26) | 112 |
btn_close |
手动关门 | 电平开关 (自定) | IO31 (PIO31) | 126 |
btn_alarm |
报警 | 电平开关 3 | IO48 (PIO48) | 161 |
⚠️ 极重要(已验证):GW48 实验箱的电平开关极性与直觉相反!
- 拨到右侧(L) = 输出高电平
- 拨到左侧(H) = 输出低电平
(注:旧版可能有上下之分,新板子上标的是 H(左) / L(右),不管哪种,代码中已统一做了取反处理) 因此代码中已对这 3 个信号做了取反处理(
btn_alarm_inv <= not btn_alarm等)。 默认状态下,所有电平开关应拨到 L 侧(无操作)。需要触发功能时拨到 H 侧。
模式 NO.5 下,PIO16~PIO47 共 8 组 4 位 BCD 码经外部全译码器驱动 8 个数码管。
⚠️ 关键(已验证):模式 NO.5 的数码管不接受 7 位段码!必须输出 4 位 BCD 码。 代码中已将display_driver模块替换为直接输出 BCD 码的组合逻辑。
我们只使用数码管 1(PIO16~PIO19)显示楼层,其余数码管显示的内容为 FPGA 其他输出的 BCD 解读(无实际意义,可忽略)。
| 端口信号 | PIO 名 | EP3C40 引脚号 | 说明 |
|---|---|---|---|
| seg7[0] | PIO16 | 56 | BCD bit 0(楼层最低位) |
| seg7[1] | PIO17 | 57 | BCD bit 1 |
| seg7[2] | PIO18 | 63 | BCD bit 2(始终为 0) |
| seg7[3] | PIO19 | 68 | BCD bit 3(始终为 0) |
| seg7[4] | PIO20 | 69 | 数码管 2 的一部分(无意义) |
| seg7[5] | PIO21 | 70 | 数码管 2 的一部分(无意义) |
| seg7[6] | PIO22 | 73 | 数码管 2 的一部分(无意义) |
数码管 1 的 BCD 显示对照:
| 楼层 | seg7[3..0] BCD 码 | 数码管显示 |
|---|---|---|
| 1楼 | 0001 | 1 |
| 2楼 | 0010 | 2 |
| 3楼 | 0011 | 3 |
模式 NO.5 下,PIO32PIO39 的输出**经 BCD 译码器显示在数码管 56 上**,而非驱动 LED。
| 端口信号 | 功能 | PIO 标准名 | EP3C40 引脚号 | 显示位置 |
|---|---|---|---|---|
led_up |
上行指示 | PIO32 | 127 | 数码管 5 bit 0 |
led_dn |
下行指示 | PIO33 | 128 | 数码管 5 bit 1 |
led_door |
门状态指示 | PIO34 | 131 | 数码管 5 bit 2 |
led_alarm |
报警指示 | PIO35 | 132 | 数码管 5 bit 3 |
⚠️ 已验证的硬件限制:在 Mode NO.5 下,实验箱的 D1~D8 LED 始终常亮, 这是板载"多任务重配置"控制器的固有行为,FPGA 无法控制这些 LED。
- D1~D8:由模式控制器固定驱动,始终亮(正常现象)
- D9
D16:由键 18 的电平状态控制(按键切换亮/灭)- LED 指示信号(上行/下行/开门/报警)可通过数码管 5~6 的数值间接观察
如需直接通过 LED 观察状态,需换用其他模式(如 Mode NO.0),但键和数码管的接法也会相应改变。
| 端口信号 | 系统资源 | 标准名 | EP3C40 引脚号 |
|---|---|---|---|
buzzer |
扬声器 | SPEAKER | 164 |
- 点击菜单 Assignments → Pin Planner
- 窗口下方会显示一个表格,列出
elevator_top的所有端口信号名- 如果表格为空,说明工程还没编译过,需要先执行 Processing → Start → Start Analysis & Elaboration
对于每个端口信号:
- 在表格中找到对应的信号名(如
clk) - 双击该行的 Location 列
- 输入引脚号(如
PIN_152),或从下拉列表中选择 - 按 Enter 确认
- 重复以上步骤,直到所有信号都分配完毕
💡 快捷操作:也可以使用 Assignments → Assignment Editor,在 Category 下拉框中选择
All或Locations,然后在 To 列和 Location 列中逐行填写。
以下为你需要在 Assignment Editor 中填写的完整引脚列表:
| To (信号名) | Location (引脚) |
|---|---|
clk |
PIN_152 |
rst_n |
PIN_18 |
btn_up1 |
PIN_21 |
btn_up2 |
PIN_22 |
btn_dn2 |
PIN_37 |
btn_dn3 |
PIN_38 |
btn_go1 |
PIN_39 |
btn_go2 |
PIN_41 |
btn_go3 |
PIN_43 |
btn_open |
PIN_112 |
btn_close |
PIN_126 |
btn_alarm |
PIN_161 |
seg7[0] |
PIN_56 |
seg7[1] |
PIN_57 |
seg7[2] |
PIN_63 |
seg7[3] |
PIN_68 |
seg7[4] |
PIN_69 |
seg7[5] |
PIN_70 |
seg7[6] |
PIN_73 |
led_up |
PIN_127 |
led_dn |
PIN_128 |
led_door |
PIN_131 |
led_alarm |
PIN_132 |
buzzer |
PIN_164 |
- 在 Assignment Editor 中确认所有 24 个引脚都已正确分配
- 点击 File → Save(或 Ctrl+S)保存
由于 GW48 实验箱 Mode NO.5 的硬件特性,elevator_top.vhd 必须做以下修改才能正常工作:
模式 NO.5 的数码管自带外部 BCD→7 段译码器,不能直接接收 7 位段码。
打开 elevator_top.vhd,找到 display_driver 实例化部分(约在"第 6 节"),替换为:
-- 6. 数码管输出(BCD 码,适配 GW48 模式 NO.5 外部译码器)
process(w_current_floor)
begin
case w_current_floor is
when "00" => seg7 <= "0000001"; -- 1楼: BCD 0001
when "01" => seg7 <= "0000010"; -- 2楼: BCD 0010
when "10" => seg7 <= "0000011"; -- 3楼: BCD 0011
when others => seg7 <= "0000001"; -- 默认1楼
end case;
end process;GW48 电平开关极性与直觉相反(下=高,上=低)。在 elevator_top.vhd 的内部信号声明区添加:
signal btn_alarm_inv : std_logic;
signal btn_open_inv : std_logic;
signal btn_close_inv : std_logic;在 begin 后添加取反逻辑:
btn_alarm_inv <= not btn_alarm;
btn_open_inv <= not btn_open;
btn_close_inv <= not btn_close;将三个 debounce 实例的 btn_in 分别改为 btn_alarm_inv、btn_open_inv、btn_close_inv。
FPGA 上电后可能产生假脉冲导致报警误触发。添加启动延迟计数器:
signal startup_cnt : std_logic_vector(5 downto 0);
signal startup_done : std_logic;在 begin 后添加计数进程:
process(w_clk_1hz, rst_n)
begin
if rst_n = '0' then
startup_cnt <= (others => '0');
startup_done <= '0';
elsif rising_edge(w_clk_1hz) then
if startup_done = '0' then
if startup_cnt = "000010" then
startup_done <= '1';
else
startup_cnt <= startup_cnt + 1;
end if;
end if;
end if;
end process;将 alarm_controller 实例的 alarm_cancel 改为:
alarm_cancel => not startup_done, -- 启动期间自动取消报警💡 以上修改已包含在最新版
src/elevator_top.vhd中,如果你使用的是最新代码则无需手动改。
引脚锁定 + 代码修改后必须重新编译。
- 点击菜单 Processing → Start Compilation
- 或快捷键 Ctrl + L
- 或工具栏上的紫色 ▶ 按钮
- 等待编译完成(大约 1~3 分钟)
⚠️ 许可证提醒:如果 Fitter 阶段报错Current license file does not support the EP3C40Q240C8 device,说明许可证无效。需要安装支持 Cyclone III 的有效许可证(Quartus II Web Edition 免费支持 Cyclone III)。
- 确认 Messages 窗口显示
Info: Quartus II Full Compilation was successful - 如果看到
Warning: Can't generate programming files because you are currently using the Quartus II software in Evaluation Mode,说明许可证问题未解决,.sof 文件不会生成 - 检查是否有关键警告:
Warning: inferred latch→ 必须修复- 引脚相关警告 → 正常可忽略
- 编译成功后,在工程目录下会生成
elevator_top.sof文件
- 关闭实验箱电源
- 将 USB 下载器(USB-Blaster)的 USB 端插入电脑
- 将 USB 下载器的 10 芯扁平线端 连接到 GW3C40 适配板上的 JTAG PORT 10 芯座
⚠️ 注意方向:线缆上的红色标记(1 号引脚)要对准插座的 1 号引脚标记⚠️ 必须插 JTAG PORT,不是 AS PORT(适配板上可能有两个 10 芯座)
- 确认适配板(GW3C40)在主板插座上压紧
- 打开实验箱电源
- 检查电脑是否识别了 USB-Blaster:
- 打开 Windows 设备管理器
- 在"通用串行总线控制器"下应能看到 Altera USB-Blaster
- 如果未识别,需要安装 USB-Blaster 驱动:
- 驱动位于 Quartus II 安装目录下:
C:\altera\91\quartus\drivers\usb-blaster\
- 驱动位于 Quartus II 安装目录下:
- 点击菜单 Tools → Programmer
- 弹出 Programmer 编程窗
- 在 Programmer 窗口中,检查左上角 Hardware Setup 旁边是否显示
USB-Blaster [USB-0] - 如果显示 No Hardware:
a. 点击 Hardware Setup... 按钮
b. 选择 Hardware Settings 页
c. 双击列表中的 USB-Blaster
d. 确认 Currently selected hardware 显示为
USB-Blaster [USB-0]e. 点击 Close
- Mode 下拉框选择
JTAG(通常是默认值) - 确认文件列表中显示
elevator_top.sof- 如果没有,点击 Add File... → 浏览到工程目录 → 选择
elevator_top.sof ⚠️ .sof文件在工程根目录下,不在db或incremental_db子文件夹里
- 如果没有,点击 Add File... → 浏览到工程目录 → 选择
- 勾选 文件右侧的 Program/Configure 复选框
- 点击 Start 按钮
- 观察下方的 Progress 进度条
- 当显示 100% (Successful) 时,下载成功!
⚠️ JTAG 下载是临时配置,断电后配置丢失。如需掉电保护,请参见第十节。如果报错
Can't access JTAG chain,请检查:
- 实验箱电源是否打开
- 排线是否插紧(红边对准缺口)
- 适配板是否压紧
- 重新拔插 USB 线,然后点 Auto Detect 测试
- 确认模式选择显示为
5(模式 NO.5) - 确认 CLOCK0 跳线在 50MHz 位置
⚠️ 将所有电平开关拨到下方(此时实际输出高电平,代码中已取反处理,等效为"无操作")- 按一下系统复位键
- 按一下键 1(释放 rst_n,系统开始运行)
⚠️ 等待 2~3 秒!(代码有启动保护延迟,前 2 秒忽略所有按键防止误触发)
等待启动完成后,观察:
| 观察项 | 预期结果 | 说明 |
|---|---|---|
| 数码管 1 | 显示 1 | 1 楼(BCD 码) |
| 数码管 2~8 | 显示杂数字 | 正常,未驱动的 PIO 显示随机值 |
| LED D1~D4 | 灭 | 无方向/无开门/无报警 |
| LED D5~D8 | 常亮 | 正常,对应 PIO 未驱动(弱上拉) |
| 蜂鸣器 | 静音 | 启动保护已取消误触发 |
- 按键 8(
btn_go3,去 3 楼)- 操作:按一次使其输出高电平(旁边 LED D16 亮起)。
- 注意:由于键 8 是 Toggle 开关,按完后它会持续输出高电平!为了避电梯"认为"你一直按在 3 楼,到达 3 楼后需要再按一次键 8,使其输出变回低电平(D16 熄灭)。
- 观察运行:
- 数码管 5 显示为
1(0001取代led_up高电平),表示上行。 - 数码管 1 显示楼层逐步变化:1 → 2 → 3(每秒变化一次)。
- 数码管 5 显示为
- 到达 3 楼并开门:
- 到达 3 楼后,数码管 5 的 bit 0 变
0(上行结束)。 - 数码管 5 的 bit 2 变
1(显示值变为4即0100),表示 开门(led_door)。 - 蜂鸣器短响约 0.5 秒(到站提示音)。
- 到达 3 楼后,数码管 5 的 bit 0 变
- 关门与返回:
- 约 10 秒后,开门时间到,数码管 5 的 bit 2 变
0,表示关门成功。 - 此时如果没有人在按键(确保键 8 已经被再次按下熄灭!),电梯会自动返回 1 楼。
- 数码管 5 显示为
2(0010取代led_dn高电平),表示下行。 - 数码管 1:3 → 2 → 1。
- 回到 1 楼后,下行结束,停在空闲状态。
- 约 10 秒后,开门时间到,数码管 5 的 bit 2 变
- 当门开着时(数码管 5 显示
4),将标有IO31的电平开关(位于最底层开关组中)拨到H侧(左侧)- 门应提前关闭(数码管 5 变为
0) - 测试完后立刻拨回
L侧
- 门应提前关闭(数码管 5 变为
- 当门关着时,将标有
IO26的电平开关(同最底层开关组)拨到H侧(左侧)- 门会重新打开(数码管 5 变为
4) - 测试完后立刻拨回
L侧
- 门会重新打开(数码管 5 变为
- 将电平开关 3 (
IO48)拨到H侧 再迅速拨回L侧(产生一次动作脉冲) - 观察:
- 数码管 5 的 bit 3 以约 1Hz 频率闪烁(数值在
8和0间跳变) - 蜂鸣器规律鸣响 (0.5秒响,0.5秒停)
- 电梯停止运行
- 数码管 5 的 bit 3 以约 1Hz 频率闪烁(数值在
- 将电平开关 3 (
IO48) 再次拨到H侧并拨回L侧(产生第二次动作脉冲)- 报警解除,电梯恢复正常,如果没有人按其他楼层则自动返回 1 楼。
| 测试项 | 预期行为 | 实际结果 | 通过? |
|---|---|---|---|
| 复位状态 | 数码管1显示"1",数码管5显示"0",蜂鸣器静音 | ||
| 上行至3楼 | 数码管1: 1→2→3,数码管5显示"1" | ||
| 到站蜂鸣 | 到达时短响0.5s | ||
| 10秒自动关门 | 数码管5显示"4",10秒后变"0" | ||
| 手动关门 | 拨开关2到上方后,门提前关闭 | ||
| 报警功能 | 数码管5显示"8"闪烁,蜂鸣长响,电梯停 | ||
| 空闲返回1楼 | 数码管1: 3→2→1,数码管5显示"2" |
JTAG 下载的配置在断电后会丢失。如果需要上电自动恢复,需要将配置文件烧录到 EPCS Flash 中。
- 在 Programmer 窗口中,Mode 选择
Active Serial Programming - 打开编程文件,选择
elevator_top.pof - 勾选 3 个编程操作项目
- 适配板跳线设为 AS 模式
- 10 芯线连接到适配板的 AS PORT
- 点击 Start
- 将
.sof文件转换为.jic文件:- File → Convert Programming Files...
- Programming file type 选 JTAG Indirect Configuration File (.jic)
- Configuration device 选择对应的 EPCS 型号
- 添加
.sof文件 - 点击 Generate
- 在 Programmer 中加载
.jic文件,通过 JTAG 口烧录
原因:下载器与 FPGA 芯片通信失败
解决(按优先级排查):
⚠️ 实验箱电源没开(最常见原因!)- 排线插错了接口(应插 JTAG PORT,不是 AS PORT)
- 排线没插紧或插反(红边对准缺口 Pin 1)
- 适配板(GW3C40)没压紧 → 向下按一按
- 重新拔插 USB 线 → 在 Programmer 中点 Auto Detect
原因:Quartus II 处于 Evaluation Mode,无有效许可证
症状:Assembler 报告中出现 Warning: Can't generate programming files because you are currently using the Quartus II software in Evaluation Mode
解决:
- 检查 Tools → License Setup... 中是否有有效的许可证文件
- Quartus II Web Edition 免费支持 Cyclone III,可从 Intel/Altera 官网获取许可证
- 向实验室老师索取配套许可证文件
原因:GW48 电平开关极性与代码预期相反,导致报警误触发
解决:
- 确认
elevator_top.vhd中已做电平开关取反处理(5.2 节) - 确认已添加启动延迟保护(5.3 节)
- 所有电平开关默认拨到下方
- 重新编译下载
原因:输出 7 位段码而非 4 位 BCD 码
解决:确认已按 5.1 节将 display_driver 替换为 BCD 输出逻辑
原因:对应的 PIO36~PIO39 未被设计驱动,弱上拉导致默认高电平
说明:这是正常现象,不影响功能。只需关注 D1~D4。
原因:模式不对或 CLOCK0 未接
解决:
- 确认模式为 NO.5(按选择键直到显示
5,然后按系统复位键) - 确认 CLOCK0 跳线在 50MHz
- 按键 1 释放 rst_n → 等待 2~3 秒(启动保护期间无法操作)
- 确认顶层实体是
elevator_top,不是elevator_ctrl
| 特性 | 说明 |
|---|---|
| 键 1~8 | 高低电平发生器(toggle 切换) |
| 电平开关 | |
| 数码管 | 8 组 4 位 BCD 码经外部译码器驱动 |
| LED D1~D8 | PIO32~39,高电平点亮 |
| CLOCK0 | 50MHz 用于 clk_divider 分频 |
📌 完成检查清单
- 目标器件已切换为 EP3C40Q240C8
- 顶层实体为
elevator_topclk_divider.vhd分频常量是 50MHz 原始值elevator_top.vhd已完成 GW48 适配修改(BCD + 取反 + 启动延迟)- 所有 24 个引脚已完成分配
- 编译成功无错误,
.sof文件已生成- CLOCK0 跳线在 50MHz
- 实验箱模式设为 NO.5
- 所有电平开关拨到下方
- USB-Blaster 连接并被识别
- JTAG 下载 100% 成功
- 按键 1 释放复位后等 2~3 秒
- 数码管 1 显示 "1",D1~D4 灭,蜂鸣器静音
- 按键 8 后数码管 1 变化 1→2→3
- 到站蜂鸣、自动关门、报警功能测试通过