此号不用改用道法自然了

74HC595驱动LED--FPGA设计技巧与案例开发详解

1
阅读(3505)
module led_74595_driver
/*--------------------------------------------------------------
Author			:		zhiqiuyiye
Email Address	:		liangwenhao0603@163.com
Filename			:		led_74595_driver.v
Data				:		2016-06-11
Description			:		The driver of led via serial ic 74hc595.

Data			By		Version	        Change Description
===========================================================================
16/6/11		zhiqiuyiye		1.0		Original
===========================================================================
*/
`timescale 1ns/1ns
module led_74595_driver
(
	input			clk,
	input			rst_n,
	
	output		led595_dout,
	output		led595_clk,
	output		led595_latch,
	
	input			[7:0]	led_data
);

//-----------------------------
//update led display when led_data is update
reg	[7:0]		led_data_r = 8'h00;
reg				updata_flag;
always@(posedge clk or negedge rst_n)
begin 
	if(!rst_n)
		begin
		led_data_r <= 0;
		updata_flag <= 1;
		end
	else 
		begin
		led_data_r <= led_data;
		updata_flag <= (led_data_r != led_data) ? 1'b1 : 1'b0;
		end
end 
//-----------------------------
//74hc595 clk delay for enough setup time
localparam	DELAY_CNT = 3'D7;
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) ? delay_cnt+1'b1:3'd0;
	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;
//-----------------------------

//-----------------------------
//74hc595 shift data output state
reg	[3:0] led_cnt;
always@(posedge clk or negedge rst_n)
begin 
	if(!rst_n)
		begin 
		led_cnt <= 0;
		shift_state <= 0;
		end 
	else
		begin
		case(shift_state)
		0:	begin
			led_cnt <= 0;
			if(updata_flag)
				shift_state <= 1;
			else 
				shift_state <= 0;
			end 
		1:	begin
			if(shift_flag)
					begin
					if(delay_cnt < 4'd8)
						begin
						led_cnt <= led_cnt + 1'b1;
						shift_state <= 1'd1;
						end 
					else 
						begin
						led_cnt <= 0;
						shift_state <= 0;
						end 
					end 
			else 
				begin
				led_cnt <= led_cnt;
				shift_state <= shift_state;
				end 
			end 
			endcase  
		end 
end

//-----------------------------
assign	led595_dout = (shift_state == 1'b1 && led_cnt < 4'd8) ? led_data[3'd7 - led_cnt] : 1'b0;
assign	led595_clk  = (shift_state == 1'b1 && led_cnt < 4'd8) ? shift_clk : 1'b0;
assign	led595_latch = (shift_state == 1'b1 && led_cnt == 4'd8) ? 1'b1 : 1'b0;
//-----------------------------
endmodule
module	LED_74595_Driver_TB;
`timescale 1ns/1ns

module	LED_74595_Driver_TB;

//-----------------------------------
//clock generate module
reg clk;
reg rst_n;
localparam PERIOD = 20;
initial
begin
	clk = 0;
	forever #(PERIOD/2)
	clk = ~clk;
end 

task task_reset;
begin
	rst_n = 0;
	repeat(2)@(negedge clk);
	rst_n = 1;
end
endtask
//-----------------------------------
//the driver of 74hc595
reg [7:0]	led_data;
led_74595_driver		 u_led_74595_driver
(
	//global clock
	.clk				(clk),
	.rst_n				(rst_n),

	//74hc595 interface
	.led595_dout		(led595_dout),	//74hc595 serial data input	
	.led595_clk			(led595_clk),	//74hc595 shift clock (rising edge)
	.led595_latch		(led595_latch),	//74hc595 latch clock (risign edge)

	//user interface
	.led_data			(led_data)		//led data input	
);
//-----------------------------------
//---------------------------------------
//system initialization
task task_sysinit;
begin
	led_data = 0;
end
endtask
//----------------------------------------
//testbench of the RTL
initial
begin
	task_sysinit;
	task_reset;
	
	#2000;
	led_data = 8'hA2;
	
	#2000;
	led_data = 8'hCB;
end
endmodule

blob.png

blob.png

blob.png

blob.png