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

登录以开始

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

1.芯片原理图

2.时序图(Timing diagram)

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
专注电子设计
点击跳转