module hc595_driver(
input clk, //50Mhz
input rst_n, //复位信号
input [15:0] data, //数码管待显示数据,8位段选数据,8位位选数据
input en, //使能
output reg ds, //串行数据输出(74hc595)
output reg sh_cp, //移位寄存器的时钟输出(74hc595)
output reg st_cp //存储寄存器的时钟输出(74hc595)
);
parameter CNT_MAX = 3; //分频器的计数值
reg [15:0] divider_cnt;
wire sck_pluse;
reg [4:0] shcp_edge_cnt;
//对系统时钟进行计数,即得模4计数器(divider_cnt)
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
divider_cnt <= 16'd0;
else if(en)begin
if(divider_cnt == CNT_MAX)
divider_cnt <= 16'd0;
else
divider_cnt <= divider_cnt + 1'b1;
end
end
//对系统时钟50Mhz进行分频,4分频,得到sck_pluse(12.5Mhz)
assign sck_pluse = (divider_cnt == CNT_MAX);
//对sck_pluse进行计数,即shcp_edge_cnt为模32的计数器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
shcp_edge_cnt <= 5'd0;
else if(sck_pluse)begin
if(shcp_edge_cnt == 5'd31)
shcp_edge_cnt <= 5'd0;
else
shcp_edge_cnt <= shcp_edge_cnt + 1'b1;
end
else
shcp_edge_cnt <= shcp_edge_cnt;
end
//线性序列机,用LUT实现数据的串行输入以及移位时钟sh_cp与存储时钟st_cp的产生
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sh_cp <= 1'b0;
st_cp <= 1'b0;
ds <= 1'b0;
end
else begin
case(shcp_edge_cnt)
5'd0: begin sh_cp <= 1'b0; st_cp <= 1'b1; ds <= data[15];end
5'd1: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd2: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[14];end
5'd3: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd4: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[13];end
5'd5: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd6: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[12];end
5'd7: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd8: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[11];end
5'd9: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd10: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[10];end
5'd11: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd12: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[9];end
5'd13: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd14: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[8];end
5'd15: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd16: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[7];end
5'd17: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd18: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[6];end
5'd19: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd20: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[5];end
5'd21: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd22: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[4];end
5'd23: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd24: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[3];end
5'd25: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd26: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[2];end
5'd27: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd28: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[1];end
5'd29: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
5'd30: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= data[0];end
5'd31: begin sh_cp <= 1'b1; st_cp <= 1'b0; end
default: begin sh_cp <= 1'b0; st_cp <= 1'b0; ds <= 1'b0;end
endcase
end
end
endmodule