电子大神的日记本,供应链专家的功夫茶盘,在这里记录、分享与共鸣。

登录以开始

[博客大赛]74HC595-串行并出驱动器

1.芯片原理图

2.时序图(Timing diagram)

![](file:///C:/Users/CDY/AppData/Local/YNote/Data/chendeyong526@yahoo.cn/d1fb7a2088c94ff8a206ab0427f0746a/clipboard.png)

3.根据时序图编写74hc595的verilog驱动程序

功能:根据输入的8bits数据data_in,通过sclk,sda,slatch来更新74hc595的数据输出。

思路:

(1)用一个状态机,1个状态用于检测data_in数据是否更新,第2个状态用于将data_in数据通过串行端口传送出去;

(2)sclk的时钟不能超过10MHz,因此需要用一个计数器(delay_cnt)来控制sclk的频率;

(3)用一个计数器(bit_cnt)来控制传送的位数(8bit)。

//filename : diver_74hc595.v

//Author : Crazy_bingo

//date : 2014.4.22

//function block:

// clk ->|-----|->sclk

// rst_n ->| |->sda

// data_in=>|-----|->slatch

module diver_74hc595(

input wire clk, //50MHz

input wire rst_n,

input wire[7:0] data_in,

output wire sclk, //lower than 10MHz

output wire sda,

output wire slatch

);

//update output when data_in is update

reg[7:0] data_r = 8'h00;

reg update_flag;

always @(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

data_r <= 0;

update_flag <= 1'b1; //when reset, update the dada_r

end

else

begin

data_r <= data_in;

update_flag <= (data_in != data_r)? 1'b1 : 1'b0;

end

end

//clk delay for enough setup time and fmax(10MHz)

localparam DELAY_CNT = 3'd7; //This parameter can be changed for different clk.

localparam WAIT_UPDATE = 1'b0;//state code

localparam SHIFT_DATA = 1'b1;//state code

reg [2:0] delay_cnt;

reg shift_state; //led scan state

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

delay_cnt <= 0;

else if(shift_state == 1'b1)

delay_cnt <= (delay_cnt == DELAY_CNT) ? 3'd0 : delay_cnt + 1'b1;

else

delay_cnt <= 0;

end

wire shift_flag = (delay_cnt == DELAY_CNT) ? 1'b1 : 1'b0;

wire shift_clk = (delay_cnt > DELAY_CNT/2) ? 1'b1 : 1'b0;

//shift data state-machine

//state code is in the front part

reg[3:0] bit_cnt;

always @(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

shift_state <= WAIT_UPDATE;

bit_cnt <= 0;

end

else

begin

case (shift_state)

WAIT_UPDATE:

begin

bit_cnt <= 0;

if(update_flag)

shift_state <= SHIFT_DATA;

else

shift_state <= WAIT_UPDATE;

end

SHIFT_DATA :

begin

if(shift_flag)//every bit_cnt will be last for DELAY_CNT,

begin //because shift_flag will be '1' for just one clk-cycle

if(bit_cnt == 4'd8)

begin

bit_cnt <= 0;

shift_state = WAIT_UPDATE; //shift to WAIT_UPDATE after 8 bit transfered

end

else

begin

bit_cnt <= bit_cnt + 1'b1;

shift_state = SHIFT_DATA;

end

end

else

begin

bit_cnt <= bit_cnt;

shift_state <= shift_state;

end

end

endcase

end

end

assign sda = (shift_state == SHIFT_DATA && bit_cnt < 4'd8) ? data_in[3'd7-bit_cnt] : 1'b0;

assign sclk = (shift_state == SHIFT_DATA && bit_cnt < 4'd8) ? shift_clk : 1'b0;

assign slatch = (shift_state == SHIFT_DATA && bit_cnt == 4'd8) ? 1'b1 : 1'b0;

endmodule

博主
cdy200824@163.com
KevinChen's Blog
专注电子设计