0. 引言
在第 2 节中,我们实现了呼吸灯,这不禁让人想到,既然能让灯像呼吸一样定时调节明暗,那我们能不能用个旋钮来手动调节明暗呢?看了看 EG4S20 系列 FPGA 的数据手册,发现 YADAN Board 上的 EG4S20NG88 里边有一个内建的 ADC 模块,连接了 3 个引脚可供采样模拟信号,所以我们可以接个旋钮式电位器来提供能手动控制的信号。继续阅读数据手册发现,需要在 TangDynasty 内调用 IP Core 才能访问 ADC,所以,在本节,我们将了解如何调用 IP Core。
目录
1. 设计思路
在实现呼吸灯的时候,我们写了个 PWM_module
,“呼吸灯用完,这节实验还能接着用” 就是按功能或层次来划分模块的一个好处。这个模块能用来控制灯的亮度,如果我们想手动调节的话,只需让该模块的占空比输入引脚连上另一个能通过手来改变输出值的模块。
我们先看看 YADAN Board 的原理图,可以发现,ADC 的通道 0、5、6 分别连接了 84、86、87 号引脚,其中,84 号引脚有其他用途,而 86 和 87 号引脚可通过开发板上的排座外接元器件。
我们可选择这两个的其中一个,比如 87 号引脚,如下图所示接上一个旋转式电位器(其他类似的电位器也可以),以供后续用手改变 ADC 采样到的电压。
在安路科技官网上 EG4 的介绍页面 下方,可以下载到 ADC 的用户指南,里边介绍了如何使用这颗 FPGA 芯片内建的 ADC。
结合以上想法和资料,我们可以通过下图所示的整体结构来实现用旋钮调节灯的亮度。其中,ADC_Module
是 IP 生成器生成的用于访问 ADC 的模块,我们可以再给它套一层,让 ADC_drv
这个模块不断地反复控制 ADC 去采样,并输出结果。
2. 生成并使用访问 ADC 的 IP Core
详细阅读 ADC 的用户指南,可发现我们需要先生成用于访问 ADC 的 IP Core。即,先在 TD 工具顶部 Tools 中点击 IP Generator
。
填入想生成的模块的名字,比如 ADC_module
,然后选择存储路径,再点 OK。
在可选 IP 的列表中能找到 ADC,双击它(我也不知道为什么没有单独的确定按钮)。
就会看到配置页面,我们可以选择需要启用的 ADC 和通道,如果要通过 87 号引脚来采样,就勾上 CH6,点 OK。
文件已经生成完成,TD 工具会问要不要把它添加进项目,那当然点 Yes!
此时在 TD 工具左上角的Hierarchy Navigation
里边就能看到刚刚生成的 ADC_module
了。不过,此时它只是提供了访问 ADC 模块的基础接口,还没法直接满足我们的需求,我们需要继续阅读 ADC 的用户指南,参考里边的控制时序,写好 ADC_drv
。
详细代码请在 这个页面 阅读。有了 ADC_drv
后,就能不断地获取采样的数据了。
3. 组合 ADC 和 PWM 模块
我们再写一个专门的顶层模块 AdjustableLED_top
,组合 ADC_drv
和之前写好的 PWM_module
就完成整个系统了。要注意的是,ADC_drv
输出的数据宽度有 12 位,而只有其中高 8 位是有效精度。所以,我们例化 PWM_module
时仍然可以传参配置其分辨率为 8 位,不过,在给 duty_cycle
传入信号时,只取 ADC_drv
输出的 dout
的高 8 位就可以了。
AdjustableLED_top.v
的代码如下:
module AdjustableLED_top (input CLK_24MHz,
output LED);
// 功能:把 ADC 和 PWM 模块以一定的逻辑组合,实现旋旋钮可以调 LED 亮度
wire [11: 0] dout;
ADC_drv ADC_drv_0(
.CLK_24MHz(CLK_24MHz),
.dout(dout) // 转换结果
);
PWM_module #(8) PWM_module_0(
.clk_in (CLK_24MHz),
.en (1'b1),
.duty_cycle (dout[11: 4]), // 传入 ADC 转换结果的高 8 位
.pwm_out (LED)
);
endmodule
可以在 这个 GitHub 仓库 获取本实验的项目文件和代码,综合、烧录、拧拧旋钮,就看到类似下边动图的效果了,太神奇了。