在实现呼吸灯的时候,我们写了个 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 去采样,并输出结果。
详细阅读 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 后,就能不断地获取采样的数据了。
我们再写一个专门的顶层模块 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 仓库 获取本实验的项目文件和代码,综合、烧录、拧拧旋钮,就看到类似下边动图的效果了,太神奇了。
本系列材料共有 5 个主线章节 与 若干个额外示例,主线章节可帮助你基本了解 Verilog 与 TangDynasty 开发工具的使用方法,额外示例可在你需要开发更丰富的应用时提供参考。