📄 hc164_driver.v
字号:
module hc164_driver(
clk,
rst_n,
led,
dot,
seg_value,
hc_cp,
hc_si
);
// ---------------------------------------------------------------------------
//
// input signals
// led[3:0] : led3-led0 对应原理图中D5,D4,D3,D2四位LED灯,高电平有效。
// seg_value[15:0] :四位共阴极数码显示的数据,从高到低每4bit为数码管一位。
// dot[3:0] : 四位共阴极数码管显示的小数点位,从高到低
// hc_si : 本模块数据串行输出,hc164数据串行输入。
// hc_cp : 本模块输出,hc164时钟输入。
//
// ---------------------------------------------------------------------------
input clk;
input rst_n;
input [3 :0] led;
input [3 :0] dot;
input [15:0] seg_value;
output reg hc_cp; //HC164 Clock input active Rising edges
output hc_si; //HC164 Data input
reg [5 :0] tx_cnt;
// ---------------------------------------------------------------------------
//
// 信号命名说明
// hc_data : 送到两个hc164中16bit的数据(每个hc164有8bit),hc164 data input
// hc_data_44bit: hc_data的第四个4BIT数据,
// LED显示信号,对应原理图中HC_Q15,HC_Q14,HC_Q13,HC_Q12四位,
// 用来点亮D5,D4,D3,D2四位LED灯,高电平有效。
// hc_data_34bit: hc_data的第三个4bit数据,即hc_data[11:8];对应原理图中
// HC_Q11,HC_Q10,HC_Q9,HC_Q8数码管位选信号,低电平有效。
// hc_data_31bit: hc_data的第三个1bit数据,即hc_data[2];对应原理图中HC_Q2,数
// 码管小数点位,高电平有效。
// hc_data[7:0]: 包括hc_data_31bit,这8bit用来做为数码管段选信号,高电平有效
//
// ---------------------------------------------------------------------------
reg [6:0] hex2led; //hex-to-seven-segment decoder output
reg [3:0] hc_data_34bit;
reg hc_data_31bit;
wire [15:0] hc_data = {led,
hc_data_34bit,
hex2led[6:2],
hc_data_31bit,
hex2led[1:0]
};
// ---------------------------------------------------------------------------
//
// 之所以需要取反,是因为对hc_si赋值时从最低位开始,而原理图中设计希望从最高位
// 开始发送数据。
//
// ---------------------------------------------------------------------------
wire [15:0] hc_data_inv = {
hc_data[0],
hc_data[1],
hc_data[2],
hc_data[3],
hc_data[4],
hc_data[5],
hc_data[6],
hc_data[7],
hc_data[8],
hc_data[9],
hc_data[10],
hc_data[11],
hc_data[12],
hc_data[13],
hc_data[14],
hc_data[15]
};
reg [15:0] clk_cnt;
always @ ( posedge clk or negedge rst_n )
if ( !rst_n ) clk_cnt <= 16'd0;
else clk_cnt <= clk_cnt + 1'b1;
// ---------------------------------------------------------------------------
//
// 数据管4位计数器,本计数器用来区分每位数值,位码,以及每位的小数点等三个
// 信息,每一位数值将通过hex2led模块变换成数码管位码。
//
// ---------------------------------------------------------------------------
reg [1:0] seg_led_num;
always @ ( posedge clk or negedge rst_n )
if (!rst_n ) seg_led_num <= 2'b00;
else if ( clk_cnt == 16'hFFFF ) seg_led_num <= seg_led_num + 1'b1;
reg [3:0] hex;
always @ ( * )
case ( seg_led_num )
2'b00: hex = seg_value[15:12];
2'b01: hex = seg_value[11:8];
2'b10: hex = seg_value[7:4];
2'b11: hex = seg_value[3:0];
endcase
// ---------------------------------------------------------------------------
// hex-to-seven-segment decoder
//
// segment encoding
// 11
// ---
// 10 | | 7
// --- <- 5
// 1 | | 4
// --- . 3
// 2
// Q[6:0] = p11 p10 p7 p5 _ p4 p2 p1
// ---------------------------------------------------------------------------
always @ ( * )
begin
case (hex) //数值
4'h1 : hex2led = 7'b0010_100; //1
4'h2 : hex2led = 7'b1011_011; //2
4'h3 : hex2led = 7'b1011_110; //3
4'h4 : hex2led = 7'b0111_100; //4
4'h5 : hex2led = 7'b1101_110; //5
4'h6 : hex2led = 7'b1101_111; //6
4'h7 : hex2led = 7'b1010_100; //7
4'h8 : hex2led = 7'b1111_111; //8
4'h9 : hex2led = 7'b1111_100; //9
4'hA : hex2led = 7'b1111_101; //A
4'hB : hex2led = 7'b0101_111; //b
4'hC : hex2led = 7'b1100_011; //C
4'hD : hex2led = 7'b0011_111; //d
4'hE : hex2led = 7'b1101_011; //E
4'hF : hex2led = 7'b1101_001; //F
default : hex2led = 7'b1110_111; //0
endcase
end
always @ ( * )
case ( seg_led_num )
2'b00:hc_data_34bit[3:0] = 4'b0111;
2'b01:hc_data_34bit[3:0] = 4'b1011;
2'b10:hc_data_34bit[3:0] = 4'b1101;
2'b11:hc_data_34bit[3:0] = 4'b1110;
endcase
always @ ( * )
case ( seg_led_num )
2'b00:hc_data_31bit = dot[3];
2'b01:hc_data_31bit = dot[2];
2'b10:hc_data_31bit = dot[1];
2'b11:hc_data_31bit = dot[0];
endcase
// ---------------------------------------------------------------------------
//
// HC164 的 hc_si 以及hc_cp信号的产生,通过一个6位的计数器来控制.hc_si从信号
// hc_data_inv的最低位开始发送,原理图中需要从最高位发送,因此在此之前需要对整
// 个信号取反。
//
// ---------------------------------------------------------------------------
always @ ( posedge clk or negedge rst_n )
if (!rst_n ) tx_cnt <= 6'd0;
else if ( clk_cnt[15] ) tx_cnt <= 6'd0;
else if ((!clk_cnt[15]) && (tx_cnt <= 6'd32 )) tx_cnt <= tx_cnt + 1'b1;
always @ ( posedge clk or negedge rst_n )
if (!rst_n) hc_cp <= 1'b0;
else if ( clk_cnt[15] ) hc_cp <= 1'b0;
else if ((!clk_cnt[15]) && (tx_cnt < 6'd32 )) hc_cp <= !hc_cp;
assign hc_si = hc_data_inv[tx_cnt[4:1]];
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -