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
用户403664 2014-4-24 09:49
用户658643 2014-4-23 21:22
用户658643 2014-4-23 21:21