数字IC设计学习笔记
8位7段数码管1
1 原理图
2 Verilog 代码
3 Modelsim仿真
1. 原理图
8位数码管
数码管内部结构图
- 数码管分为共阴极数码管和共阳极数码管;本文采用共阳极数码管。每个数码管内部的led灯的所有阳极连在一起,给正电压;当三极管的基极为高电平,三极管导通,VCC通过电阻,三极管加载到led灯的阳极。当led灯阴极为低电平,led灯点亮;当led灯阴极为高电平,led灯灭。
由于无法同时点亮8个数码管中单一的一个led灯,故采用动态扫描实现。
动态扫描:将操作平均共分为不同的时间段,如:8个数码管,分为8ms,则:
1ms: sel0 = 1, sel1 = 0; sel2 = 0;…sel7 = 0, a=0; 数码管0的led0亮;
2ms: sel0 = 0, sel1 = 1; sel2 = 0;sel7 = 0, b=0; 数码管1的led1亮;
3ms: sel0 = 0, sel1 = 0; sel2 = 1; sel7 = 0, c=0; 数码管2的 led2亮;
…
8ms: sel0 = 0, sel1 = 0; sel2 = 0; sel7 = 1, c=0; 数码管7的led7亮;
每1ms切换一次,故需要分频,得到一个1KHzd的时钟clk_1k,当clk_1k的第一个上升沿到来时,数码管0亮,第二个上升沿到来时数码管1亮…。
–>div - 控制端a,b,c,d,e,f,g段码需要由显示数据控制,显示数据通过对输入数据译码得到。第1毫秒的时候a,b,c,d,e,f,g,h对应1段码组合;第2毫秒的时候a,b,c,d,e,f,g,h对应2的段码组合…,涉及到显示内容的切换,每一毫秒,显示内容都是不一样的,如:
数码管0,显示1:1ms, 9ms, 17ms, 25ms, 33ms, 41ms, 49ms, 57ms -->a,b,c,d,e,f,g,h呈现1对应的段码;
数码管1,显示2:2ms, 10ms, 18ms, 26ms, 34ms, 42ms, 50ms, 58ms -->a,b,c,d,e,f,g,h呈现2对应的段码;
数码管2,显示3:3ms, 11ms, 19ms, 27ms, 35ms, 43ms, 51ms, 59ms -->a,b,c,d,e,f,g,h呈现3对应的段码;
…
数码管7,显示3:8ms, 16ms, 24ms, 32ms, 40ms, 48ms, 56ms, 64ms -->a,b,c,d,e,f,g,h呈现3对应的段码;
段码的状态每1ms也要切换一次–>带显示内容切换每1ms也要切换一次
每个数码管的显示数据:4位的输入数据data[3:0];
8个数码管的显示数据:8 * 4位的输入数据data[3:0] = 32位的输入数据data[31:0];
–>MUX8-1 - MUX8-1的选择控制端为当前扫描的数码管位置,sel[7:0],依次循环左移1位。
–>shift8
低功耗时,控制数码管显示与否<=>控制sel的状态,如果sel的值为全0,则数码管处于全灭状态;
–>MUX2-1
单一数码管工作原理
–>LUT, 4位输入,8位输出
原理图
实验现象:
在Quartus中,使用in system source and probes editor, 输入需要显示在数码管上的数据,数码管显示对应的数字。
2 Verilog 代码
//----top module---------------------------------
module hex8(
input clk,
input rst_n,
input en,
input [31:0] data,
output reg [6:0] seg,
output [7:0] sel
);
reg [14:0] cnt_d;
reg clk_1k;
reg [7:0] sel_reg;
reg [3:0] data_reg;
//----div----------------------------------
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_d <= 15'd0;
else if(!en)
cnt_d <= 15'd0;
else if(cnt_d == 15'd24_999)
cnt_d <= 0;
else
cnt_d <= cnt_d + 15'd1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
clk_1k <= 0;
else if(cnt_d == 15'd24_999)
clk_1k <= ~clk_1k;
else
clk_1k <= clk_1k;
//----shift8-------------------------------
always@(posedge clk_1k or negedge rst_n)
if(!rst_n)
sel_reg <= 8'b0000_0001;
else if(sel_reg == 8'b1000_0000)
sel_reg <= 8'b0000_0001;
else
sel_reg <= sel_reg << 1;
//----MUX8-1-------------------------------
always@(*)begin
case(sel_reg)
8'b0000_0001: data_reg <= data[3:0];
8'b0000_0010: data_reg <= data[7:4];
8'b0000_0100: data_reg <= data[11:8];
8'b0000_1000: data_reg <= data[15:12];
8'b0001_0000: data_reg <= data[19:16];
8'b0010_0000: data_reg <= data[23:20];
8'b0100_0000: data_reg <= data[27:24];
8'b1000_0000: data_reg <= data[31:28];
default: data_reg <= 4'd0;
endcase
end
//----LUT-----------------------------------
always@(*)begin
case(data_reg)
4'd0: seg <= 7'b000_0001;
4'd1: seg <= 7'b100_1111;
4'd2: seg <= 7'b001_0010;
4'd3: seg <= 7'b000_0110;
4'd4: seg <= 7'b100_1100;
4'd5: seg <= 7'b010_0100;
4'd6: seg <= 7'b010_0000;
4'd7: seg <= 7'b000_1111;
4'd8: seg <= 7'b000_0000;
4'd9: seg <= 7'b000_0100;
4'd10: seg <= 7'b000_1000;
4'd11: seg <= 7'b110_0000;
4'd12: seg <= 7'b011_0001;
4'd13: seg <= 7'b100_0010;
4'd14: seg <= 7'b011_0000;
4'd15: seg <= 7'b011_1000;
// default: seg <= 000_0000;
endcase
end
//----MUX2-1---------------------------------
assign sel = (en)? sel_reg:8'd0;
endmodule
//-------------------------------------------------
//----testbench--------------------------------
`timescale 1ns/1ns
`define clock_period 20
module tb_hex8;
reg clk;
reg rst_n;
reg en;
reg [31:0] data;
wire [6:0] seg;
wire [7:0] sel;
hex8 uut(
.clk(clk),
.rst_n(rst_n),
.en(en),
.data(data),
.seg(seg),
.sel(sel)
);
initial clk = 1;
always #(`clock_period/2) clk = ~clk;
initial begin
rst_n = 0;
en = 1;
data = 32'h12345678;
#(`clock_period*20);
rst_n = 1;
#(`clock_period*20);
#20000000;
data = 32'h87654321;
#20000000;
data = 32'h89abcdef;
#20000000;
$stop;
end
endmodule
3. Modelsim仿真
内容源自对小梅哥FPGA自学笔记的总结^^
【注】:个人学习笔记,如有错误,望不吝赐教,这厢有礼了~~~