差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
点亮led灯 [2016/06/02 11:28] anran [代码设计] |
点亮led灯 [2016/08/03 19:34] (当前版本) zhijun |
||
---|---|---|---|
行 1: | 行 1: | ||
- | ====硬件平台==== | + | 正如C程序初学者尝试的第一个程序是写一个“hello World”一样,FPGA初学者的第一个程序一般都为“心跳(heart beat)灯”,也就是通过系统的时钟进行分频,产生周期性的低频信号(高、低电平交替变化驱动LED),控制LED灯的点亮和熄灭。 |
------ | ------ | ||
- | [[STEP-MXO2第一代]] | + | ===硬件平台:=== |
- | + | 我们以[[STEP-MXO2第一代]]为例,对于其它平台只需要注意其时钟的频率以及管脚的分配。 | |
- | ====设计要求==== | + | |
------ | ------ | ||
+ | ===设计要求:=== | ||
- 初步了解数字设计的基本思想和开发流程 | - 初步了解数字设计的基本思想和开发流程 | ||
- | - 熟悉Diamond软件和仿真软件的使用方法及流程 | + | - 熟悉[[Lattice Diamond的使用|Diamond软件]]和仿真软件的使用方法及流程 |
- 控制LED闪烁,闪烁周期为1秒 | - 控制LED闪烁,闪烁周期为1秒 | ||
- | + | - 了解FPGA时钟的使用 | |
- | ====工作原理==== | + | - 了解时钟分频的工作原理 |
+ | \\ | ||
+ | ------ | ||
+ | ===工作原理:=== | ||
按照设计要求,控制LED闪烁的周期为1秒,则LED灯需要点亮0.5s,然后熄灭0.5s,然后点亮0.5s,然后熄灭0.5s,循环执行。 | 按照设计要求,控制LED闪烁的周期为1秒,则LED灯需要点亮0.5s,然后熄灭0.5s,然后点亮0.5s,然后熄灭0.5s,循环执行。 | ||
通过上面的分析,我们发现LED的控制信号就是一个周期为1s,占空比为50%的信号,我们可以定义一个寄存器和一个计数器,计数器负责计数满0.5s时寄存器翻转,实现对LED的闪烁控制。 | 通过上面的分析,我们发现LED的控制信号就是一个周期为1s,占空比为50%的信号,我们可以定义一个寄存器和一个计数器,计数器负责计数满0.5s时寄存器翻转,实现对LED的闪烁控制。 | ||
- | 小脚丫开发板晶振为25MHz,0.5s对应晶振12500000个周期的时间,所以计数器对晶振信号计数,当计12500000个数时,控制寄存器翻转。 | + | 开发板上晶振为25MHz,0.5s对应晶振12500000个周期的时间,所以计数器对晶振信号计数,当计12500000个数时,控制寄存器翻转。 |
- | + | ------ | |
- | ====硬件连接==== | + | ===硬件连接:=== |
LED也叫发光二极管,可以把电能转化成光能,因为是二极管的一种,由一个PN接组成,具有单向导电性。它的正向伏安特性曲线很陡,使用时必须串联限流电阻以控制通过二极管的电流,LED的亮度与电流有关,一般LED能够承受的最大电流为20mA(具体需要看使用的LED的参数),本设计使用的限流电阻为1K。下图为LED的硬件电路: | LED也叫发光二极管,可以把电能转化成光能,因为是二极管的一种,由一个PN接组成,具有单向导电性。它的正向伏安特性曲线很陡,使用时必须串联限流电阻以控制通过二极管的电流,LED的亮度与电流有关,一般LED能够承受的最大电流为20mA(具体需要看使用的LED的参数),本设计使用的限流电阻为1K。下图为LED的硬件电路: | ||
行 30: | 行 31: | ||
^ LED模块 |LED1 | | ^ LED模块 |LED1 | | ||
^ FPGA管脚 |A3 | | ^ FPGA管脚 |A3 | | ||
+ | ^ | ||
- | ====代码设计==== | + | ------ |
- | ===设计文件=== | + | ===代码设计:=== |
+ | |||
+ | ==设计文件:== | ||
+ | 模块框图如下: | ||
+ | {{ :blink.jpg |Blink}} | ||
我们首先定义一个参数:parameter CNT_NUM = 12500000 ,我们将参数定义放在模块的端口声明中,这样在模块被其他模块调用时可以通过端口重新定义参数的值。 | 我们首先定义一个参数:parameter CNT_NUM = 12500000 ,我们将参数定义放在模块的端口声明中,这样在模块被其他模块调用时可以通过端口重新定义参数的值。 | ||
行 40: | 行 46: | ||
然后使用计数器计数触发寄存器信号不断翻转,如下: | 然后使用计数器计数触发寄存器信号不断翻转,如下: | ||
- | + | <code verilog> | |
- | {{:计数及翻转.jpg|计数器计数触发寄存器翻转}} | + | reg [23:0] cnt; |
- | + | reg clk_div; | |
- | ===测试文件=== | + | always@(posedge clk_in or negedge rst_n_in) begin |
+ | if(!rst_n_in) begin | ||
+ | cnt <= 24'd0; | ||
+ | clk_div <= 1; | ||
+ | end else begin | ||
+ | if(cnt>=CNT_NUM-1) begin | ||
+ | cnt <= 24'd0; | ||
+ | clk_div <= ~clk_div; | ||
+ | end else cnt <= cnt + 1; | ||
+ | end | ||
+ | end | ||
+ | </code> | ||
+ | \\ | ||
+ | ==测试文件:== | ||
测试文件,也称testbench文件,是一种验证的手段,testbench文件在软件环境中模拟实际环境,产生被测模块输入端口需要的激励信号,对被测模块的输出信号分析,达到评估被测模块的目的。 | 测试文件,也称testbench文件,是一种验证的手段,testbench文件在软件环境中模拟实际环境,产生被测模块输入端口需要的激励信号,对被测模块的输出信号分析,达到评估被测模块的目的。 | ||
对于测试文件,我们需要提供被测模块(Blink)需要的时钟(sys_clk)及复位(sys_rst_n),如下: | 对于测试文件,我们需要提供被测模块(Blink)需要的时钟(sys_clk)及复位(sys_rst_n),如下: | ||
+ | <code verilog> | ||
+ | reg sys_clk; | ||
+ | initial | ||
+ | sys_clk = 1'b0; | ||
+ | always | ||
+ | sys_clk = #(CLK_PERIOD/2) ~sys_clk; | ||
+ | |||
+ | reg sys_rst_n; //active low | ||
+ | initial | ||
+ | begin | ||
+ | sys_rst_n = 1'b0; | ||
+ | #100; | ||
+ | sys_rst_n = 1'b1; | ||
+ | end | ||
+ | </code> | ||
+ | \\ | ||
+ | 然后调用被测模块(Blink),注意模块调用时参数的重定义及端口的传递,为了方便仿真,减少仿真时间,我们将设计文件中的计数终值参数(CNT_NUM)在测试文件中重新赋值为10,这样我们在仿真时计数器的计数范围应该为0~9。 | ||
- | {{:产生激励信号.jpg|产生激励信号}} | + | 模块调用方法如下: |
- | + | <code verilog> | |
- | 然后调用被测模块(Blink),注意模块调用时参数的重定义及端口的传递。如下 | + | blink #(.CNT_NUM(10)) blink_uut( |
- | + | .clk_in (sys_clk), | |
- | {{:模块调用参数及端口传递.jpg|模块调用参数及端口传递}} | + | .rst_n_in (sys_rst_n), |
- | + | .led_out (led_out) | |
- | + | ); | |
+ | </code> | ||
+ | \\ | ||
引脚分配如下: | 引脚分配如下: | ||
^ 管脚名称 | clk_in | rst_n_in | led_out | | ^ 管脚名称 | clk_in | rst_n_in | led_out | | ||
^ FPGA管脚 | C1 | B1 | A3 | | ^ FPGA管脚 | C1 | B1 | A3 | | ||
- | ====系统运行==== | ||
- | {{:系统运行1.jpg?300 |系统运行1}} | + | ------ |
+ | ===仿真结果:=== | ||
- | {{:系统运行2.jpg?300 |系统运行2}} | + | {{:仿真结果.jpg|仿真结果}} |
- | + | ------ | |
- | {{:系统运行3.jpg?300|系统运行3}} | + | ===资源报告:=== |
- | ====资源报告==== | + | |
^ 资源 | 数量 | 比例 | 说明 | | ^ 资源 | 数量 | 比例 | 说明 | | ||
- | ^ LUTs | 134 | 10% | | | + | ^ LUTs | 36 | 3% | | |
- | ^ 寄存器 | 88 | 6% | | | + | ^ 寄存器 | 25 | 2% | | |
^ 存储器 | 0 | 0% | | | ^ 存储器 | 0 | 0% | | | ||
- | ^ IO管脚 | 5 | | | | + | ^ IO管脚 | 3 | | | |
^ 时钟频率 | 25MHz | | | | ^ 时钟频率 | 25MHz | | | | ||
- | ====知识点==== | + | ------ |
+ | === 学习的知识点: === | ||
+ | * LED闪烁原理 | ||
+ | * FPGA时钟的使用 | ||
* 时钟分频 | * 时钟分频 | ||
- | * 串行/并行转换 | ||
- | * 数码管动态显示 | ||
- | ====参考文档==== | + | ------ |
+ | === 参考阅读: === | ||
* {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} | * {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} | ||
- | * {{:sn74hc595.pdf|74HC595数据手册}} | ||
- | |||
- | ====相关文档==== | ||
+ | ------ | ||
+ | === 相关设计文档: === | ||
^ **文件名称** | **功能** | | ^ **文件名称** | **功能** | | ||
- | ^ **[[DLED_DISP]]** | **数码管显示** | | + | ^ **[[Blink]].v** | **LED闪烁** | |
+ | ^ **[[Blink_test]].v** | **测试文件** | | ||
+ | ------ | ||
+ | === 扩展实验: === | ||
+ | XO2 FPGA自带时钟发生器,但其精度较低(5%),对于基本的功能性的实验是够了的,但对于高精度要求的应用,其芯片内部振荡器产生的时钟就无法满足要求,因此在我们的小脚丫开发板上还连接了外部晶振产生的25MHz的时钟信号,在上述的实验中我们采用了25MHz的时钟信号来产生LED的交替控制信号,用户可以尝试采用内部的时钟产生所需要的LED控制信号。 | ||