**这是本文档旧的修订版!**

DLED_DISP程序

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: DLED_DISP
// 
// Author: Step
// 
// Description: Display with Nixie tube
// 
// Web: www.ecbcamp.com
// 
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2015/11/11   |Initial ver
// --------------------------------------------------------------------
module DLED_DISP
(
input clk_in, //25mhz
input rst_n_in, //active with low 
 
output reg rclk_out, //74HC595 RCK
output reg sclk_out, //74HC595 SCK
output reg sdio_out  //74HC595 SER
);
 
parameter CLK_DIV_PERIOD=3900; //related with clk_div's frequency
parameter DELAY_PERIOD=10000;  //related with delay time and refresh frequency
parameter CLK_DIV_PULSE_PERIOD=25000000; //related with clk_div_pulse_out's frequency
 
parameter CLK_L=2'd0;
parameter CLK_H=2'd1;
parameter CLK_RISING_DEGE=2'd2;
parameter CLK_FALLING_DEGE=2'd3;
parameter IDLE=3'd0;
parameter WRITE=3'd1;
parameter DELAY=3'd2;
parameter LOW =1'b0;
parameter HIGH =1'b1;
 
//initial for memory register
reg[7:0] mem [15:0]; 
initial begin
    mem[0]= 8'h3f;   //  0
    mem[1]= 8'h06;   //  1
    mem[2]= 8'h5b;   //  2
    mem[3]= 8'h4f;   //  3
    mem[4]= 8'h66;   //  4
    mem[5]= 8'h6d;   //  5
    mem[6]= 8'h7d;   //  6
    mem[7]= 8'h07;   //  7
    mem[8]= 8'h7f;   //  8
    mem[9]= 8'h6f;   //  9
	mem[10]= 8'h77;   //  A
    mem[11]= 8'h40;   //  b
    mem[12]= 8'h39;   //  C
    mem[13]= 8'h5e;   //  d
    mem[14]= 8'h79;   //  E
    mem[15]= 8'h71;   //  F
end 
 
//clk_div_1Hz = clk_in/CLK_DIV_PULSE_PERIOD
reg[24:0] cnt;
reg clk_div_1Hz;
always@(posedge clk_in or negedge rst_n_in)
	begin
		if(!rst_n_in) begin 
			cnt<=0;
			clk_div_1Hz<=0;
		end else if(cnt==(CLK_DIV_PULSE_PERIOD-1)) begin
			cnt<=0;
			clk_div_1Hz<=1;
		end else begin
			cnt<=cnt+1;  
			clk_div_1Hz<=0;
		end
	end
 
reg [3:0] number = 0;
reg [3:0] number_r = 1;
reg [3:0] number_r1 = 2;
reg [3:0] number_r2 = 3;
//generate the number need to display every second
always@(posedge clk_div_1Hz or negedge rst_n_in)
	begin
		if(!rst_n_in) begin 
			number<=4'd3;
			number_r<=4'd2;
			number_r1<=4'd1;
			number_r2<=4'd0;
		end else begin
			number_r2<=number_r1;
			number_r1<=number_r;
			number_r<=number;
			if(number>=9) number<=0;
			else  number<=number+1;  
		end
	end
 
//clk_div = clk_in/CLK_DIV_PERIOD
reg clk_div; 
reg[11:0] clk_cnt=0;
always@(posedge clk_in or negedge rst_n_in) begin
	if(!rst_n_in) clk_cnt<=0;
	else begin
		clk_cnt<=clk_cnt+1;  
		if(clk_cnt==(CLK_DIV_PERIOD-1)) clk_cnt<=0;
		if(clk_cnt<(CLK_DIV_PERIOD/2)) clk_div<=0;
		else clk_div<=1;
	end
end
 
//Divide clk_div 4 state, 
//RISING and FALLING state is keeped one cycle of clk_in, like a pulse.
reg[1:0] clk_div_state=CLK_L;  
always@(posedge clk_in or negedge rst_n_in) begin
	if(!rst_n_in) clk_div_state<=CLK_L;
    else case(clk_div_state)
			CLK_L: begin
					if (clk_div) clk_div_state<=CLK_RISING_DEGE;  
					else clk_div_state<=CLK_L;
				end
			CLK_RISING_DEGE :clk_div_state<=CLK_H;  
			CLK_H:begin                 
					if (!clk_div) clk_div_state<=CLK_FALLING_DEGE;
					else clk_div_state<=CLK_H;
				end 
			CLK_FALLING_DEGE:clk_div_state<=CLK_L;  
			default;
		endcase
end
 
//Finite State Machine, 
reg shift_flag = 0;
reg[15:0] data_reg; 
reg[2:0] data_state=IDLE; 
reg[2:0] data_state_back; 
reg[3:0] data_state_cnt=0;  
reg[5:0] shift_cnt=0; 
reg[25:0] delay_cnt=0;  
always@(posedge clk_in or negedge rst_n_in) begin
	if(!rst_n_in) begin 
		data_state<=IDLE;
		data_state_cnt<=0;
	end else begin 
		case (data_state)
			IDLE: begin
				data_state_cnt<=data_state_cnt+1;
				case(data_state_cnt)
					0: begin 
						data_reg<={mem[number_r2],8'h2e};
						data_state<=WRITE;data_state_back<=IDLE; 
					   end
					1: begin 
						data_reg<={mem[number_r1],8'h2d};
						data_state<=WRITE;data_state_back<=IDLE; 
					   end
					2: begin 
						data_reg<={mem[number_r],8'h2b};
						data_state<=WRITE;data_state_back<=IDLE; 
					   end
					3: begin 
						data_reg<={mem[number],8'h27};
						data_state<=WRITE;data_state_back<=IDLE; 
					   end
					4: begin data_state_cnt<=0; end
					default;
				endcase
			end
			WRITE: begin
				if(!shift_flag) begin
					if (clk_div_state==CLK_FALLING_DEGE) begin
						if (shift_cnt==10) rclk_out<=LOW;
						if (shift_cnt==16) begin
							shift_cnt<=0;
							rclk_out<=HIGH;
							data_state<=data_state_back;
						end else begin
							sclk_out<=LOW;
							sdio_out<=data_reg[15];   
							shift_flag <= 1;
						end
					end
				end else begin
					if (clk_div_state==CLK_RISING_DEGE) begin  
						data_reg<={data_reg[14:0], data_reg[15]};  
						shift_cnt<=shift_cnt+1;
						sclk_out<=HIGH;
						shift_flag <= 0;
					end
				end
			end
			DELAY: begin
				if(delay_cnt==DELAY_PERIOD) begin
					data_state<=IDLE; 
					delay_cnt<=0;
				end else delay_cnt<=delay_cnt+1;
			end
 
			default;
		endcase
	end
end
 
endmodule