|
本帖最后由 chun912 于 2017-7-25 09:51 编辑
文章摘要:本文主要描述了数码管扫描电路的实现方案;
知识要点:有限状态机,模块例化;
硬件平台: EP4CE6F17C8
开发环境: Quartus II 13.1
数码管扫描模块:
- /*
- * 功能描述:6位数码管扫描模块
- */
- module smg_scan(
- input clk, // 时钟信号
- input rst_n, // 复位信号
- output reg[7:0]data_pin, // 数据引脚,共阳数码管
- output reg[5:0]sel_pin, // 选通引脚,低电平导通
- input [7:0]seg0, // 数据0
- input [7:0]seg1, // 数据1
- input [7:0]seg2, // 数据2
- input [7:0]seg3, // 数据3
- input [7:0]seg4, // 数据4
- input [7:0]seg5 // 数据5
- );
-
- //--------------------------------------------------
- // 有限状态机
- parameter S_SEG0 = 4'd1;
- parameter S_SEG1 = 4'd2;
- parameter S_SEG2 = 4'd3;
- parameter S_SEG3 = 4'd4;
- parameter S_SEG4 = 4'd5;
- parameter S_SEG5 = 4'd6;
- reg[3:0] state; // 记录当前状态
- /*
- * 全部刷新时间不能超过10ms,否则人眼可以感觉到闪烁
- * 如果刷新时间缩短至5ms以内,则低速摄像机也扑捉不到闪烁
- */
- parameter FLUSH_COUNT = 50_000; // 单个刷新时间1ms,全部刷新时间为6ms
- reg[31:0] count; // 刷新记数器
- always @(posedge clk, negedge rst_n) begin
- if(!rst_n) begin
- sel_pin <= 6'b111111; // 复位时关闭显示
- state <= S_SEG0; // 回到初始状态
- end
-
- else if(count >= FLUSH_COUNT) begin // 定时时间到
- count <= 0; // 重新计数
-
- case(state)
- S_SEG0: begin
- state <= S_SEG1;
- sel_pin <= 6'b111110; // 片选
- data_pin <= seg0; // 数据
- end
-
- S_SEG1: begin
- state <= S_SEG2;
- sel_pin <= 6'b111101;
- data_pin <= seg1;
- end
- S_SEG2: begin
- state <= S_SEG3;
- sel_pin <= 6'b111011;
- data_pin <= seg2;
- end
-
- S_SEG3: begin
- state <= S_SEG4;
- sel_pin <= 6'b11_0111;
- data_pin <= seg3;
- end
-
- S_SEG4: begin
- state <= S_SEG5;
- sel_pin <= 6'b10_1111;
- data_pin <= seg4;
- end
-
- S_SEG5: begin
- state <= S_SEG0; // 最后一个显示完,下一次该显示示第一个了
- sel_pin <= 6'b01_1111;
- data_pin <= seg5;
- end
-
- default: begin
- state <= S_SEG0; // 未知状态,返回第一个状态
- end
- endcase
- end
-
- else begin
- count <= count + 1'b1; // 最后一个时钟沿其实是没计数的;
- end
-
- end
- endmodule
复制代码
译码器计数器模块:
- /*
- * 功能描述:异步十进制译码计数器
- */
- module decoder(
- clk, // 计数时钟
- rst_n, // 异步复位
- seg, // 译码输出
- carry // 进位(做为下级时钟)
- );
- input clk;
- input rst_n;
- output reg [7:0] seg;
- output reg carry;
- //------------------------------------------
- reg [3:0] count; // 计数器
- // 十进制计数器
- always @(posedge clk or negedge rst_n) begin
- if(~rst_n) begin
- count <= 0;
- carry <= 1'b0;
- end
- else if(count < 9) begin
- count <= count + 1'b1;
- carry <= 1'b0;
- end
- else begin
- count <= 0;
- carry <= 1'b1; // 产生进位
- end
- end
- // 组合逻辑
- always @(*) begin
- if(~rst_n) begin
- seg <= 8'b1111_1111; // 全灭
- end
- else begin
- case(count)
- 4'd0:
- seg <= 8'b1100_0000;
- 4'd1:
- seg <= 8'b1111_1001;
- 4'd2:
- seg <= 8'b1010_0100;
- 4'd3:
- seg <= 8'b1011_0000;
- 4'd4:
- seg <= 8'b1001_1001;
- 4'd5:
- seg <= 8'b1001_0010;
- 4'd6:
- seg <= 8'b1000_0010;
- 4'd7:
- seg <= 8'b1111_1000;
- 4'd8:
- seg <= 8'b1000_0000;
- 4'd9:
- seg <= 8'b1001_0000;
- 4'd10:
- seg <= 8'b1000_1000;
- default:
- seg <= 8'hff;
- endcase
- end
- end
- endmodule
复制代码
建立顶层模块(测试用)
- /*
- * 功能描述:数码管测试程序
- */
- module smg_test(
- input clk, // 系统时钟
- input rst_n, // 系统复位
- output [7:0]data_pin, // 数据管数据脚
- output [5:0]sel_pin // 数码管片选脚
- );
- reg[31:0] timer; // 定时器
- reg tick;
- // 模块连接线
- wire[7:0]seg0;
- wire[7:0]seg1;
- wire[7:0]seg2;
- wire[7:0]seg3;
- wire[7:0]seg4;
- wire[7:0]seg5;
- wire[7:0]seg6;
- wire c0; // 计数器进位
- wire c1;
- wire c2;
- wire c3;
- wire c4;
- //-----------------------------------------------
- always @(posedge clk or negedge rst_n) begin
- if(~rst_n)
- begin
- timer <= 0;
- tick <= 0;
- end
- else if(timer == 32'd25_000_000)
- begin
- tick <= 1'b1;
- timer <= 0;
- end
- else begin
- tick <= 0;
- timer <= timer + 1'b1;
- end
- end
- // 例化数码管显示模块
- smg_scan s0(
- .clk(clk), // 时钟信号
- .rst_n(rst_n), // 复位信号
- .data_pin(data_pin), // 数据引脚,共阳数码管
- .sel_pin(sel_pin), // 选通信号,低电平导通
- .seg0(seg0), // 数据
- .seg1(seg1), // 数据
- .seg2(seg2), // 数据
- .seg3(seg3), // 数据
- .seg4(seg4), // 数据
- .seg5(seg5) // 数据
- );
- // 例化6个显示译码器,用于将数字转化为显示段码;
- decoder u0(
- .clk(tick), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg0), // 译码输出
- .carry(c0) // 进位
- );
- decoder u1(
- .clk(c0), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg1), // 译码输出
- .carry(c1) // 进位
- );
- decoder u2(
- .clk(c1), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg2), // 译码输出
- .carry(c2) // 进位
- );
- decoder u3(
- .clk(c2), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg3), // 译码输出
- .carry(c3) // 进位
- );
- decoder u4(
- .clk(c3), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg4), // 译码输出
- .carry(c4) // 进位
- );
- decoder u5(
- .clk(c4), // 计数时钟
- .rst_n(rst_n), // 异步复位
- .seg(seg5), // 译码输出
- .carry() // 进位
- );
- endmodule
复制代码
|
|