CPLDで時計を作ってみる2

 前回の続きになります。

この前途中まで作っていた回路の配線と残りの部品を追加しました。
7セグ周りの配線とスイッチ類が追加されました。

若干CPLDのポートへの接続も変更しました。
回路図も更新しておきます。

CPLDロジックはこんな感じです。

まず基準となるクロックを発振器から作りだします。
10MHzのクロックを分周して7セグのダイナミック点灯用の1kHzイネーブルと
その1kHzイネーブルを利用して1sのイネーブルを生成しています。

時計本体は下記カウンタを用意し、各カウンタの桁上がり信号を
カスケード接続しています。
「1sのイネーブル」

「6進カウンタ(10秒)」
↓桁上がり
「10進カウンタ(60秒)」
↓桁上がり
「6進カウンタ(10分)」
↓桁上がり
「6進カウンタ(60分)」
↓桁上がり
「24進カウンタ(24時間)」

カウンタの出力を7セグで表示しています。
7セグはダイナミック点灯させています。

スイッチ入力から時刻合わせ機能も作ってみました。
よく考えて作ったわけではないので、とりあえず時刻合わせができるという感じです。

CPLDのロジック使用率は96%となりました。

カウントアップ

時刻合わせ

ソースコード

//*****************************************************************************
// CPLD Clock
//*****************************************************************************

//=============================================================================
//include
//=============================================================================

//=============================================================================
//Definition
//=============================================================================

//*****************************************************************************
// Top_CPLD_Clock
//*****************************************************************************
module Top_CPLD_Clock
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire [7:0] SW,			//時刻設定スイッチ
	output wire[7:0] LED,		//デバック用LED
	output wire[7:0] SEG,		//7セグLED
	output wire[5:0] SEGSEL		//点灯セグ選択
);

	//--------------------------------------------
	//register
	//--------------------------------------------
	//--------------------------------------------
	//wire
	//--------------------------------------------
	wire EN_1ms;
	wire EN_1s;
	wire CA_1s;
	wire CA_10s;
	wire CA_1m;
	wire CA_10m;
	
	wire [1:0] DIG10;
	wire [3:0] DIG1;
	wire [2:0] count6_10m;
	wire [3:0] count10_1m;
	wire [2:0] count6_10s;
	wire [3:0] count10_1s;
	
	wire RST;
	wire [7:0] SWDATA;
	wire MIN_Inc;
	wire HOUR_Inc;
	
	assign RST  = 1'b1;

	//--------------------------------------------
	//モジュール間の接続
	//--------------------------------------------
	//カウンタの接続
	EN1ms	EN1ms		(CLK,RST,EN_1ms);
	EN1s	EN1s		(CLK,RST,EN_1ms,EN_1s);
	CNT10	SEC_1s	(CLK,SWDATA[0]&SWDATA[1],EN_1s,CA_1s,count10_1s);
	CNT6	SEC_10s	(CLK,SWDATA[0]&SWDATA[1],CA_1s,CA_10s,count6_10s);
	CNT10	MIN_1m	(CLK,SWDATA[0],CA_10s|MIN_Inc,CA_1m,count10_1m);
	CNT6	MIN_10m	(CLK,SWDATA[0],CA_1m,CA_10m,count6_10m);
	CNT24	HOUR		(CLK,SWDATA[0],CA_10m|HOUR_Inc,DIG1,DIG10);

	//ダイナミック点灯
	Dynamic	Dynamic	(CLK,EN_1ms,DIG10,DIG1,count6_10m,count10_1m,count6_10s,count10_1s,SEGSEL,SEG);

	//スイッチ入力
	Chattering Chattering (CLK,RST,SW[7:0],SWDATA[7:0]);
	SWEN	MINInc	(CLK,RST,EN_1ms,~SWDATA[2],MIN_Inc);
	SWEN	HOURInc	(CLK,RST,EN_1ms,~SWDATA[3],HOUR_Inc);
	
endmodule

//*****************************************************************************
// EN1ms
// 10MHzクロックから1kHzイネーブルを生成
//*****************************************************************************
module EN1ms
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	output wire EN_1ms
);
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [13:0] Count_1ms = 14'd0;	//14bit

	//--------------------------------------------
	//10MHzクロックから1kHzを生成
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0) begin
			Count_1ms <= 14'd0;
		end
		else if(EN_1ms == 1'd1) begin
			Count_1ms <= 14'd0;
		end
		else begin
			Count_1ms <= Count_1ms + 14'd1;
		end
	end

	assign EN_1ms = (Count_1ms == 14'd9999);

endmodule

//*****************************************************************************
// CNT1s
// イネーブル付10bitカウンタ(1Hzイネーブル生成)
//*****************************************************************************
module EN1s
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	input wire EN,
	output wire EN_1s
);
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [9:0] Count_1s= 10'd0;		//10bit

	//--------------------------------------------
	//1kHzクロックから1Hzを生成
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0)begin
			Count_1s <= 10'd0;
		end
		else if(EN == 1'd1) begin
			if(Count_1s == 10'd999) begin
				Count_1s <= 10'd0;
			end
			else begin
				Count_1s <= Count_1s + 10'd1;
			end
		end
	end
	
	assign EN_1s = (Count_1s == 10'd999) & EN;

endmodule

//*****************************************************************************
// CNT10
// イネーブル付10進カウンタ
//*****************************************************************************
module CNT10
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	input wire EN,
	output wire CA,
	output reg [3:0] Count10
);
	//--------------------------------------------
	//10進カウンタ
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0)begin
			Count10 <= 4'd0;
		end
		else if(EN == 1'd1) begin
			if(Count10 == 4'd9) begin
				Count10 <= 4'd0;
			end
			else begin
				Count10 <= Count10 + 4'd1;
			end
		end
	end
	
	assign CA = (Count10 == 4'd9) & EN;

endmodule

//*****************************************************************************
// CNT6
// イネーブル付6進カウンタ
//*****************************************************************************
module CNT6
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	input wire EN,
	output wire CA,
	output reg [2:0] Count6
);
	//--------------------------------------------
	//6進カウンタ
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0)begin
			Count6 <= 3'd0;
		end
		else if(EN == 1'd1) begin
			if(Count6 == 3'd5) begin
				Count6 <= 3'd0;
			end
			else begin
				Count6 <= Count6 + 3'd1;
			end
		end
	end
	
	assign CA = (Count6 == 3'd5) & EN;

endmodule

//*****************************************************************************
// CNT24
// イネーブル付24進カウンタ
//*****************************************************************************
module CNT24
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	input wire EN,
	output reg [3:0] DIG1,
	output reg [1:0] DIG10
);	
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [4:0] Count24;

	//--------------------------------------------
	//24進カウンタ 24時間
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0)begin
			Count24 <= 5'd0;
		end
		else if(EN == 1'd1) begin
			if(Count24 == 5'd23) begin
				Count24 <= 5'd0;
			end
			else begin
				Count24 <= Count24 + 5'd1;
			end
		end
	end

	//--------------------------------------------
	//コード変換回路
	//--------------------------------------------
	always@(Count24) begin
		case (Count24)
			5'd0		:begin DIG10 <= 2'H0; DIG1	<= 4'h0;end
			5'd1		:begin DIG10 <= 2'H0; DIG1	<= 4'h1;end
			5'd2		:begin DIG10 <= 2'H0; DIG1	<= 4'h2;end
			5'd3		:begin DIG10 <= 2'H0; DIG1	<= 4'h3;end
			5'd4		:begin DIG10 <= 2'H0; DIG1	<= 4'h4;end
			5'd5		:begin DIG10 <= 2'H0; DIG1	<= 4'h5;end
			5'd6		:begin DIG10 <= 2'H0; DIG1	<= 4'h6;end
			5'd7		:begin DIG10 <= 2'H0; DIG1	<= 4'h7;end
			5'd8		:begin DIG10 <= 2'H0; DIG1	<= 4'h8;end
			5'd9		:begin DIG10 <= 2'H0; DIG1	<= 4'h9;end
			5'd10		:begin DIG10 <= 2'H1; DIG1	<= 4'h0;end
			5'd11		:begin DIG10 <= 2'H1; DIG1	<= 4'h1;end
			5'd12		:begin DIG10 <= 2'H1; DIG1	<= 4'h2;end
			5'd13		:begin DIG10 <= 2'H1; DIG1	<= 4'h3;end
			5'd14		:begin DIG10 <= 2'H1; DIG1	<= 4'h4;end
			5'd15		:begin DIG10 <= 2'H1; DIG1	<= 4'h5;end
			5'd16		:begin DIG10 <= 2'H1; DIG1	<= 4'h6;end
			5'd17		:begin DIG10 <= 2'H1; DIG1	<= 4'h7;end
			5'd18		:begin DIG10 <= 2'H1; DIG1	<= 4'h8;end
			5'd19		:begin DIG10 <= 2'H1; DIG1	<= 4'h9;end
			5'd20		:begin DIG10 <= 2'H2; DIG1	<= 4'h0;end
			5'd21		:begin DIG10 <= 2'H2; DIG1	<= 4'h1;end
			5'd22		:begin DIG10 <= 2'H2; DIG1	<= 4'h2;end
			5'd23		:begin DIG10 <= 2'H2; DIG1	<= 4'h3;end
			default	:begin DIG10 <= 2'Hx; DIG1	<= 4'hx;end
		endcase
	end
	
endmodule

//*****************************************************************************
// DynamicLighting
// 7セグLEDダイナミック点灯
//*****************************************************************************
module Dynamic
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire EN,
	input wire [1:0] DIG10,
	input wire [3:0] DIG1,
	input wire [2:0] Count6_10m,
	input wire [3:0] Count10_1m,
	input wire [2:0] Count6_10s,
	input wire [3:0] Count10_1s,
	output wire [5:0] SegSelect,
	output wire [7:0] SegLED
);	
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [2:0] Count_Seg;

	//--------------------------------------------
	//ダイナミック点灯用カウンタ
	//--------------------------------------------
	always@(posedge CLK) begin
		if(EN == 1'd1) begin
			if(Count_Seg == 3'd5) begin
				Count_Seg <= 3'd0;
			end
			else begin
				Count_Seg <= Count_Seg + 3'd1;
			end
		end
	end
	
	//--------------------------------------------
	//ダイナミック点灯入力セレクタ
	//--------------------------------------------
	function [4:0]SegData(
	input [2:0] sel
	);
	begin
		case (sel)
			3'h0		: SegData = DIG10;
			3'h1		: SegData = DIG1;
			3'h2		: SegData = Count6_10m;
			3'h3		: SegData = Count10_1m;
			3'h4		: SegData = Count6_10s;
			3'h5 		: SegData = Count10_1s;
			default	: SegData = 5'bx;
		endcase
	end
	endfunction
	
	//--------------------------------------------
	//ダイナミック点灯デコーダ
	//--------------------------------------------
	function [5:0] DEC (
		input [2:0] DECIN
	);
	begin
		case (DECIN)
			3'h5		:	DEC = 6'b0010_0000;
			3'h4		:	DEC = 6'b0001_0000;
			3'h3		:	DEC = 6'b0000_1000;
			3'h2		:	DEC = 6'b0000_0100;
			3'h1		:	DEC = 6'b0000_0010;
			3'h0		:	DEC = 6'b0000_0001;
			default	:	DEC = 6'bx;
		endcase
	end
	endfunction
	
	//--------------------------------------------
	//7セグメントLEDデコーダ
	//--------------------------------------------
	function [7:0] SEG7 (
		input [3:0] DIN
	);
	begin
		case (DIN)
			//DP,G,F,E,D,C,B,A
			4'h0		:	SEG7 = ~8'b0011_1111;//0
			4'h1		:	SEG7 = ~8'b0000_0110;//1
			4'h2		:	SEG7 = ~8'b0101_1011;//2
			4'h3		:	SEG7 = ~8'b0100_1111;//3
			4'h4		:	SEG7 = ~8'b0110_0110;//4
			4'h5		:	SEG7 = ~8'b0110_1101;//5
			4'h6		:	SEG7 = ~8'b0111_1101;//6
			4'h7		:	SEG7 = ~8'b0000_0111;//7
			4'h8		:	SEG7 = ~8'b0111_1111;//8
			4'h9		:	SEG7 = ~8'b0110_1111;//9
			default	:	SEG7 = ~8'bx;
		endcase
	end
	endfunction

	assign SegSelect[5:0] = DEC(Count_Seg);
	assign SegLED[7:0] = SEG7(SegData(Count_Seg));

endmodule

//*****************************************************************************
// Chattering
// スイッチ入力のチャタリング除去
//*****************************************************************************
module Chattering
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire clk,
	input wire RST,
	input wire [7:0] in,
	output reg [7:0] out
);
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [7:0] buffer;
	reg [15:0] Count;

	//--------------------------------------------
	//チャタリング除去
	//--------------------------------------------
	always @(posedge clk or negedge RST)begin
		if(RST == 1'd0)begin
			Count <= 1'd0;
		end
		else begin
			Count <= Count + 1'd1;
		end
	end
	
	always @(posedge clk)begin
		if(Count == 1'd0)begin
			buffer <= in;
			out <= buffer;
		end
	end

endmodule

//*****************************************************************************
// SWEN
// スイッチが押されている間100msごとにイネーブルを出力する
//*****************************************************************************
module SWEN
//--------------------------------------------
//ポート設定
//--------------------------------------------
(
	input wire CLK,
	input wire RST,
	input wire EN,
	input wire SW,
	output wire EN_SW
);
	//--------------------------------------------
	//register
	//--------------------------------------------
	reg [6:0] Count = 7'd0;		//7bit

	//--------------------------------------------
	//スイッチイネーブル
	//--------------------------------------------
	always@(posedge CLK) begin
		if(RST == 1'd0)begin
			Count <= 7'd0;
		end
		else if(EN == 1'd1) begin
			if(Count == 7'd99) begin
				Count <= 7'd0;
			end
			else begin
				Count <= Count + 7'd1;
			end
		end
	end
	
	assign EN_SW = (Count == 7'd99) & EN & SW;

endmodule

//*****************************************************************************
// 終わり
//*****************************************************************************

コメント