赞
踩
与"开发板实战篇1 LED点灯(开篇)" 的区别,增加模式切换
总结:
模块例化思想: 定时器模块 + 点灯模块
根据自己思路编写代码,调试仿真代码,同时熟悉环境.加深细节理解
segled_static_driver.v 实现不够简洁,感觉还可以优化,后面有思路再搞
注意:
若进行了QuartusII_13.0 和 Notepad++软件的关联,在modelsim中无法双击打开.v文件,只能通过工具栏的open文件夹图标打开, 我的电脑会打开altium designer软件 ,取消关联可恢复正常
每次打开modelsim时需要切换工作空间,否则可能创建工程添加的源码会是上一个仿真工程的代码,导致出错
一. 实现的功能
6位数码管以静态方式依次显示000000、 111111、222222至FFFFFF,结束后继续从000000开始计数,每1s变化一次。
二. 功能框图
定时器模块:加计数器,计数到了产生overflow信号
segled控制模块:根据en使能信号,点亮数码管
打开方法: tools -> netlist viewers -> rtl viewer
三. RTL代码
segled_static_top.v
与led_top.v基本相同。
COUNT_OVERFLOW = 26'd50_000_000,即闪烁周期为1S。
- module segled_static_top (
- input clk,
- input reset,
- output [5:0] sel,
- output [7:0] seg_led
- );
-
- parameter COUNT_OVERFLOW = 26'd50_000_000;
- wire overflow; // 定时时间到
- timer #(
- .COUNT_OVERFLOW (COUNT_OVERFLOW)
- )
- u_timer(
- .clk (clk),
- .reset (reset),
- .overflow (overflow)
- );
- segled_static_driver u_segled_static_driver(clk,reset,overflow,sel,seg_led);
-
- endmodule
timer.v
除将overflow <=修改为非阻塞赋值外,其它与led点灯工程的相同。
- /*
- ********************************************************************************
- *Copyright ©, 2018, CunXin_ All Rights Reserved
- *文 件 名: key_led.v
- *说 明:
- 程序功能无按键按下时, LED灯全灭;
- 按键1按下时, LED灯显示自右向左的流水效果;
- 按键2按下时, LED灯显示自左向右的流水效果;
- 按键3按下时,四个LED灯同时闪烁;
- 按键4按下时, LED灯全亮
- *版 本: V000B00D00
- *创建日期: 2018年4月3日 下午12:16:49
- *创 建 人: wansaiyon
- *修改信息:
- ================================================================================
- *修 改 人 修改日期 修改内容
- *<作者/修改者> <YYYY/MM/DD> <修改内容>
- ********************************************************************************
- */
-
- module timer #(
- parameter COUNT_OVERFLOW = 26'd10_000_000
- ) (
- input clk,
- input reset,
- output reg overflow
- );
- localparam period = COUNT_OVERFLOW;
- reg [25:0] cnt;
- always @(posedge clk,negedge reset) begin
- if(!reset) begin
- cnt <= 26'd0;
- overflow <= 1'b0;
- end
- else if(cnt < period) begin
- cnt <= cnt + 1'd1;
- overflow <= 1'b0;
- end
- else begin
- cnt <= 26'd0;
- overflow <= 1'b1;
- end
-
- end
- endmodule
segled_static_driver.v
主要功能:定义16个字符、显示字符状态切换、、seg_led显示输出。
- /*
- 6位数码管
- sel[0] output N16 第一个数码管位选信号
- sel[1] output N15 第二个数码管位选信号
- sel[2] output P16 第三个数码管位选信号
- sel[3] output P15 第四个数码管位选信号
- sel[4] output R16 第五个数码管位选信号
- sel[5] output T15 第六个数码管位选信号
- seg_led[0] output M11 数码管段选a
- seg_led[1] output N12 数码管段选b
- seg_led[2] output C9 数码管段选c
- seg_led[3] output N13 数码管段选d
- seg_led[4] output M10 数码管段选e
- seg_led[5] output N11 数码管段选f
- seg_led[6] output P11 数码管段选g
- seg_led[7] output D9 数码管段选h
- */
-
- module segled_static_driver (
- input clk,
- input reset,
- input en,
- output reg [5:0] sel,
- output reg [7:0] seg_led
- );
-
- // param define
- localparam CHAR_0 = 8'b0100_0000;
- localparam CHAR_1 = 8'b0111_1001;
- localparam CHAR_2 = 8'b0010_0100;
- localparam CHAR_3 = 8'b0011_0000;
- localparam CHAR_4 = 8'b0001_1001;
- localparam CHAR_5 = 8'b0001_0010;
- localparam CHAR_6 = 8'b0000_0010;
- localparam CHAR_7 = 8'b0111_1000;
- localparam CHAR_8 = 8'b0000_0000;
- localparam CHAR_9 = 8'b0001_0000;
- localparam CHAR_a = 8'b0000_1000;
- localparam CHAR_b = 8'b0000_0011;
- localparam CHAR_c = 8'b0100_0110;
- localparam CHAR_d = 8'b0010_0001;
- localparam CHAR_e = 8'b0000_0110;
- localparam CHAR_f = 8'b0000_1110;
-
- //reg define
- reg [3:0] segled_ctrl;
-
- // 显示状态切换
- always @(posedge clk,negedge reset ) begin
- if(!reset) begin
- segled_ctrl <= 4'b0000;
- end
- else if(en) begin
- segled_ctrl <= segled_ctrl + 1'b1;
- end
- else begin
- segled_ctrl <= segled_ctrl;
- end
- end
-
- // seg_led 输出显示
- always @(posedge clk ,negedge reset) begin
- if(!reset) begin
- sel <= 6'b00_0000;
- seg_led <= CHAR_8;
- end
- else if(en) begin
- sel <= 6'b00_0000;
- casex (segled_ctrl)
- 4'b0000: begin
- seg_led <= CHAR_0;
- end
- 4'b0001: begin
- seg_led <= CHAR_1;
- end
- 4'b0010: begin
- seg_led <= CHAR_2;
- end
- 4'b0011: begin
- seg_led <= CHAR_3;
- end
- 4'b0100: begin
- seg_led <= CHAR_4;
- end
- 4'b0101: begin
- seg_led <= CHAR_5;
- end
- 4'b0110: begin
- seg_led <= CHAR_6;
- end
- 4'b0111: begin
- seg_led <= CHAR_7;
- end
- 4'b1000: begin
- seg_led <= CHAR_8;
- end
- 4'b1001: begin
- seg_led <= CHAR_9;
- end
- 4'b1010: begin
- seg_led <= CHAR_a;
- end
- 4'b1011: begin
- seg_led <= CHAR_b;
- end
- 4'b1100: begin
- seg_led <= CHAR_c;
- end
- 4'b1101: begin
- seg_led <= CHAR_d;
- end
- 4'b1110: begin
- seg_led <= CHAR_e;
- end
- 4'b1111: begin
- seg_led <= CHAR_f;
- end
- default: begin
- seg_led <= CHAR_0;
- end
- endcase
- end
- else begin
- sel <= 6'b00_0000;
- seg_led <= seg_led;
- end
- end
-
- endmodule
四.modelsim前仿真(功能仿真)
每次打开modelsim时需要切换工作空间,否则可能创建工程添加的源码会是上一个仿真工程的代码,导致出错 。
使用vscode打开segled_static_top.v, ctrl+shift+p,输入testbench,在terminal生成了segled_static_top_tb.v代码,需要安装插件verilog_testbench, 初始生成时可能提示失败,需要安装 python 库(根据错误提示自行百度)。
生成的代码有点错误,需要自己再做点修改。
segled_static_top_tb.v,
为了方便减小了计数器周期为26'd10。
- `timescale 1ns / 1ns
-
- module tb_segled_static_top;
-
- // segled_static_top Parameters
- parameter PERIOD = 10 ;
- parameter COUNT_OVERFLOW = 26'd10;
- // segled_static_top Inputs
- reg clk = 0 ;
- reg reset = 0 ;
- // segled_static_top Outputs
- wire [5:0] sel ;
- wire [7:0] seg_led ;
- initial
- begin
- forever #(PERIOD/2) clk=~clk;
- end
- initial
- begin
- #(PERIOD*2) reset = 1;
- end
- segled_static_top #(
- .COUNT_OVERFLOW ( COUNT_OVERFLOW ))
- u_segled_static_top (
- .clk ( clk ),
- .reset ( reset ),
- .sel ( sel [5:0] ),
- .seg_led ( seg_led [7:0] )
- );
- endmodule
仿真波形
五.下载验证
6位数码管以静态方式依次显示000000、 111111、222222至FFFFFF,结束后继续从000000开始计数,每1s变化一次。
但是发现4个LED有微弱的亮度,需要配置好未使用管脚的状态为高阻输入,同时将nCEO管脚修改为Use as regular I/0,修改后LED变为熄灭状态了。
在 Quartus 软件中默认未使用管脚的状态为弱上拉输入,所以未使用到的管脚上也是有电压的,只是驱动能力很弱,这往往会导致一些不安全的隐患,所以我们需要将未使用管脚的状态设置为三态输入。
在左侧Category一栏中选择Dual-Purpose Pin。对于需要使用EPCS器件的引脚时,需要将下图页面中所有的引脚都改成Use as regular IO,如果大家不确定工程中是否用到EPCS器件时,可以全部修改。本次实验只修改了nCEO一栏中, 将Use as programming pin修改为Use as regular I/0。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。