## 流水灯 ### 1. 硬件平台 - [[STEP-MXO2第一代]] - [[STEP-Baseboard]] ### 2. 设计要求 - 掌握任意数分频计数功能的设计 - 掌握时序逻辑的设计 - 掌握case的基本语法 - 基于小脚丫STEP FPGA Base Board开发平台LED实现流水灯的功能,总计8个LED灯,循环、轮流点亮,每个LED点亮时间为1秒 ### 3. 工作原理 本设计为流水灯实验,我们需要结合使用的硬件平台实现[[STEP-Baseboard]]平台上的8个LED循环闪烁,每个LED灯点亮时间为1秒。 LED也叫发光二极管,属于二极管的一种,具有二极管的单项导电性,使用时需要给LED上施加正向压差,产生电流(一般在20mA以内,具体参考设计中使用的LED的参数),点亮LED。本平台使用的8个LED都是通过低电平点亮(参照电路图),因此控制该LED的FPGA的IO管脚输出“1“(高电平)时LED灭,输出”0“(低电平)时LED亮。 为了使一个循环周期内每个LED点亮1秒的时间,我们需要一个持续时间为1秒的低电平信号,这可以通过本硬件平台[[STEP-MXO2第一代]]上的25MHz主时钟得到,2^25 = 33554432 > 25000000,所以我们需要做一个位宽为25的计数器。计数器初值为0,当计数到24999999时,总共计数25000000,也就是1秒时间。 为了实现流水的效果,我们需要一个寄存器,寄存器的值不同控制着不同的LED点亮,而寄存器的值在每次计数器计数到24999999时改变,这样每隔1秒时间,寄存器的值改变,对应控制8个LED按照同一方向循环闪烁,就实现了流水灯的功能。 ### 4. 硬件连接 结合实验平台[[STEP-Baseboard]]的硬件配置,我们使用8个LED灯作为流水灯的输出 {{ :图10.LED模块电路连接.png |LED模块电路连接}} ### 5. 代码设计 #### 5.1 设计文件 {{ :流水灯程序设计.jpg |流水灯程序设计}} 为了实现对8个LED的控制,我们设计了25位的计数器cnt进行1s周期的循环计数,同时我们定义了一个3位寄存器led_cnt作为状态机的状态控制流水灯的闪烁。状态机共有8个状态,每一个状态对应点亮一个LED灯。 首先是计数器的设计,计数器的计数范围为0~CNT_NUM-1,为了实现每个LED灯1秒的点亮时间,设计文件代码中我们定义参数CNT_NUM为25000000,但是在仿真文件调用设计文件时,为了方便仿真,我们会将参数CNT_NUM重新赋值为10. reg [24:0] cnt = 25'd0; always@(posedge clk_in or negedge rst_n_in) begin if(!rst_n_in) begin cnt <= 25'd0; end else if(cnt>=CNT_NUM-1) begin cnt <= 25'd0; end else begin cnt <= cnt + 25'd1; end end 然后我们需要对状态机的状态进行控制,使得作为状态的寄存器led_cnt实现从0到7的循环加一操作。 reg [2:0] led_cnt = 3'd0; always@(posedge clk_in or negedge rst_n_in) begin if(!rst_n_in) begin led_cnt <= 3'd0; end else if(cnt==CNT_NUM-1) begin if(led_cnt==3'd7) led_cnt <= 3'd0; else led_cnt <= led_cnt + 3'd1; end end 最后是组合逻辑,根据led_cnt的不同状态控制不同的LED点亮。 always@(led_cnt) begin case(led_cnt) 3'd0: led_out = 8'b1111_1110; 3'd1: led_out = 8'b1111_1101; 3'd2: led_out = 8'b1111_1011; 3'd3: led_out = 8'b1111_0111; 3'd4: led_out = 8'b1110_1111; 3'd5: led_out = 8'b1101_1111; 3'd6: led_out = 8'b1011_1111; 3'd7: led_out = 8'b0111_1111; default: led_out = 8'b1111_1111; endcase end #### 5.2 测试文件 测试文件中我们需要对设计文件中的参数CNT_NUM进行重新赋值 parameter CNT_NUM = 10; Water_led #(.CNT_NUM(CNT_NUM)) Water_led_uut ( .clk_in(sys_clk), .rst_n_in(sys_rst_n), .led_out(led_out) ); 引脚分配如下: ^ 管脚名称 | clk_in| rst_n_in | led_out[0] |led_out[1] |led_out[2] |led_out[3] |led_out[4] |led_out[5] |led_out[6] |led_out[7] | ^ FPGA管脚 | C1 | A2 |B14 |C14 |E14 |F14 |G14 |J14 |K14 |L14 | ### 6. 仿真结果 {{:流水灯仿真.jpg|流水灯仿真}} ### 7. 资源报告 ^ 资源 | 数量 | 比例 | 说明 | ^ LUTs | 27 | 4% | | ^ 寄存器 | 28 | 2% | | ^ 存储器 | 0 | 0% | | ^ IO管脚 | 10 | | | ^ 时钟频率 | 25MHz | | | ### 8. 知识点 * 分频设计 * 时序控制 * 简单状态机 ### 9. 参考文档 * [[点亮led灯]] * {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} ### 10. 相关文档 ^ **文件名称** | **功能** | ^ **[[Water_led.v]]** | **流水灯** | ^ **[[Water_led_test.v]]** | **测试文件** |