这一篇记录定制化数码管显示模块的驱动开发
数码管的原理再常见不过了,只不过数码管也分共阴极和共阳极的,这两种的写法是相反的
为这个课题采购的数码管来源于淘宝Telsky旗舰店哈哈,我也算是他家老生意了
无非就是让这个模块改成参数化传递的罢了,和以前写过的没啥大的区别
`define SIM
module Seg_disp_sim
#(
parameter MODE = 1//共阳
)
(
input System_Clk ,//系统时钟
input Rst_n ,//系统复位
input [3:0] data_0 ,//第0位数据
input [3:0] data_1 ,//第1位数据
input [3:0] data_2 ,//第2位数据
output reg [6:0] Dig ,//段选
output reg Dp ,//小数点
output reg [2:0] Sel //位选
//others
);
//Parameters and Defines
`ifndef SIM
localparam Sample_end = 49999;//扫描周期1ms
`else
localparam Sample_end = 49;
`endif
//Regs
reg [3:0] data_0_r; //第0位数据寄存器
reg [3:0] data_1_r; //第1位数据寄存器
reg [3:0] data_2_r; //第2位数据寄存器
reg [3:0] data_reg; //实时显示数据寄存器
reg [2:0] bit_cnt; //扫描位数计数器
reg bit_flag; //扫描周期计满标志
reg [15:0] sample_cnt; //扫描周期计数器
//Main Code
//data_0-5_reg
always @(posedge System_Clk or negedge Rst_n)begin
if(Rst_n == 1'b0)begin
data_0_r <= 'd0;
data_1_r <= 'd0;
data_2_r <= 'd0;
end
else if(bit_cnt==3'd0 && sample_cnt==16'd0)begin//在一开始采样一次待显示数据并锁存
data_0_r <= data_0;//sample at bit0
data_1_r <= data_1;
data_2_r <= data_2;
end
end
//bit_flag 扫描周期计数器计满,计满标志发生一个脉冲
always @(posedge System_Clk or negedge Rst_n)begin
if(Rst_n==1'b0)
bit_flag <= 1'b0;
else if(sample_cnt==Sample_end)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
end
//bit_cnt //扫描位数计数器累加逻辑
always @(posedge System_Clk or negedge Rst_n)begin
if(Rst_n==1'b0)
bit_cnt <= 'd0;
else if(bit_cnt == 3'd2 && bit_flag==1'b1)
bit_cnt <= 'd0;
else if(bit_flag==1'b1)
bit_cnt <= bit_cnt + 1'b1;
end
//data_reg //根据扫描位数选择对应数据
always @(*)begin
case(bit_cnt)
3'd0:data_reg = data_0_r;
3'd1:data_reg = data_1_r;
3'd2:data_reg = data_2_r;
default:data_reg = 4'h0;
endcase
end
//sample_cnt 扫描计数器逻辑
always @(posedge System_Clk or negedge Rst_n)begin
if(Rst_n==1'b0)
sample_cnt <= 'd0;
else if(sample_cnt==Sample_end)
sample_cnt <= 'd0;
else
sample_cnt <= sample_cnt + 1'b1;
end
//Dig //根据数码管显示表
always @(*)begin
case(data_reg)
4'h0:Dig = MODE?~7'b1111110:7'b1111110;
4'h1:Dig = MODE?~7'b0000110:7'b0000110;
4'h2:Dig = MODE?~7'b1101101:7'b1101101;
4'h3:Dig = MODE?~7'b1111001:7'b1111001;
4'h4:Dig = MODE?~7'b0110011:7'b0110011;
4'h5:Dig = MODE?~7'b1011011:7'b1011011;
4'h6:Dig = MODE?~7'b1011111:7'b1011111;
4'h7:Dig = MODE?~7'b1110000:7'b1110000;
4'h8:Dig = MODE?~7'b1111111:7'b1111111;
4'h9:Dig = MODE?~7'b1111011:7'b1111011;
/*
4'ha:Dig = MODE?~7'b0000001:7'b0000001;
4'hb:Dig = MODE?~7'b0000000:7'b0000000;
4'hc:Dig = MODE?~7'b0000000:7'b0000000;
4'hd:Dig = MODE?~7'b0000000:7'b0000000;
4'he:Dig = MODE?~7'b0000000:7'b0000000;
4'hf:Dig = MODE?~7'b0000000:7'b0000000;
*/
default:Dig = MODE?7'b1111111:7'b0000000;
endcase
end
//sel 位选信号逻辑
always @(*)begin
case(bit_cnt)
3'd0:Sel = MODE?~3'b110:3'b110;//点亮右面第一个
3'd1:Sel = MODE?~3'b101:3'b101;
3'd2:Sel = MODE?~3'b011:3'b011;
default:Sel = MODE?3'b000:3'b111;
endcase
end
endmodule
其中通过这种写法可以以较低的代码量实现需求
4'h0:Dig = MODE?~7'b1111110:7'b1111110;
4'h1:Dig = MODE?~7'b0000110:7'b0000110;
4'h2:Dig = MODE?~7'b1101101:7'b1101101;
4'h3:Dig = MODE?~7'b1111001:7'b1111001;
4'h4:Dig = MODE?~7'b0110011:7'b0110011;
4'h5:Dig = MODE?~7'b1011011:7'b1011011;
4'h6:Dig = MODE?~7'b1011111:7'b1011111;
4'h7:Dig = MODE?~7'b1110000:7'b1110000;
4'h8:Dig = MODE?~7'b1111111:7'b1111111;
4'h9:Dig = MODE?~7'b1111011:7'b1111011;
代码能少写点就少些点了