読者です 読者をやめる 読者になる 読者になる

ledドットマトリクスをCPLDで制御する

電子工作

移転しました。

オプティマイズの1600円MAX II CPLDボードにチップをはんだづけして,使えるようにして,LEDドットマトリクスを制御してみた.LEDドットマトリクスには,何年前かに何処かで買ってきた5x7ドット緑色のもの(MD0657M-G, 1.7V 10mA)を使用.ちなみに,5x7ドットだと,行列選択に5+7=12ピンで済みますし,バッファICを入れればもっと少ないピン数で済みますので,CPLDを使わなくてもAVRなどのマイコンでも十分制御できますが,CPLDの練習のためCPLDをあえて使います.

配線は,

3.3V - E (2SA1015) C - LED - R(330 Ohm) - ROWピン(CPLD)
            B
            |- 4.7 kOhm - COLピン(CPLD)

みたいな感じに行った.
LEDは一本あたりおよそ5 mAで,7本同時にドライブすると,35 mA.
MAX II(EPM570T100C)の足一本は25 mAまでらしいので,COL側にpnpトランジスタを入れた.合計は120? mAまでいけるので,ROW側にはトランジスタはいらないと考えた.
ドライブ電源には,CPLDボードの3.3Vレギュレータの電源を流用.5V電源にはUSBポートを使う.(定格を調べていないが,一時的な実験用途なので使っている時に燃えたら燃えたで瞬時に取り外して泣くだけの話.->調べたら大丈夫でした)

Verilogコードはこのようにした.中途半端にクロックを分周したが,静止画ならば分周する必要がない.次は動画にしたいところだが,5x7bitという制限で何をするかが問題だ.

module ledmat(output [6:0] ROWS, output [4:0] COLS);

wire oscena, clk, oscout;
reg [2:0] col;

assign oscena = 1'b1;
osc osc(oscena, oscout); //3.3 MHz
division division(oscout, clk);


always @ (posedge clk) begin
	if (col == 3'h5)
		col <= 3'h1;
	else
		col <= col + 3'h1;
end

function [6:0] rdat;
input [2:0] col;
	case (col)
		3'h1: rdat = 7'b1101111;
		3'h2: rdat = 7'b1100111;
		3'h3: rdat = 7'b0000011;
		3'h4: rdat = 7'b0000001;
		3'h5: rdat = 7'b1111100;
		default: rdat = 7'b1111111;
	endcase
endfunction
assign ROWS = rdat( col );

function [4:0] cdat;
input [2:0] col;
	case (col)
		3'h1: cdat = 5'b11110;
		3'h2: cdat = 5'b11101;
		3'h3: cdat = 5'b11011;
		3'h4: cdat = 5'b10111;
		3'h5: cdat = 5'b01111;
		default: cdat = 5'b11111;
	endcase
endfunction
assign COLS = cdat( col );

endmodule

//**********clock division circuit
module division(
	input osc,
	output clk
	);

reg [5:0] counter; //@3.3 MHz: 21bit -> 0.6sec
assign clk = counter[5];
always @ (posedge osc) begin
	counter <= counter + 1'b1;
end

endmodule



「イ」が表示されるようにしてみたが,形がいびつだった.


ピンの対応表を書いた.CPLDのピンは後からソフトウェアで割り当てできるので,配線時は何も考えなくてよいのがいい.


追記:動画?としてハートマーク(あるいはv記号)が飛ぶようにしてみた.3.3 MHzでscanするとトランジスタのスイッチングが間に合っていないようでぼやっとしか光らない.結局分周は必要のようだ.

module ledmat2(output [6:0] ROWS, output [4:0] COLS);

wire oscena, clk1, clk2, oscout;
reg [2:0] col, page;
parameter pmax = 3'h7;

assign oscena = 1'b1;
osc osc(oscena, oscout); //3.3 MHz
division division(oscout, clk1, clk2);

//scan cols
always @ (posedge clk1) begin
	if (col == 3'h5)
		col <= 3'h1;
	else
		col <= col + 3'h1;
end

//increase page
always @ (posedge clk2) begin
	if (page == pmax) begin
		page <= 3'h0;
	end else
		page <= page + 3'h1;
end


function [6:0] rdat;
input [2:0] col, page;
	case (page)
		3'h0:
			case (col)
				3'h1: rdat = 7'b1011111;
				3'h2: rdat = 7'b0111111;
				3'h3: rdat = 7'b1011111;
				3'h4: rdat = 7'b1111111;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h1:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b1101111;
				3'h3: rdat = 7'b1011111;
				3'h4: rdat = 7'b1101111;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h2:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b1111111;
				3'h3: rdat = 7'b1110111;
				3'h4: rdat = 7'b1101111;
				3'h5: rdat = 7'b1110111;
				default: rdat = 7'b1111111;
			endcase
		3'h3:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b1111011;
				3'h3: rdat = 7'b1110111;
				3'h4: rdat = 7'b1111011;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h4:
			case (col)
				3'h1: rdat = 7'b1111101;
				3'h2: rdat = 7'b1111011;
				3'h3: rdat = 7'b1111101;
				3'h4: rdat = 7'b1111111;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h5:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b1111110;
				3'h3: rdat = 7'b1111101;
				3'h4: rdat = 7'b1111110;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h6:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b1111111;
				3'h3: rdat = 7'b1111111;
				3'h4: rdat = 7'b1111110;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		3'h7:
			case (col)
				3'h1: rdat = 7'b1111111;
				3'h2: rdat = 7'b0111111;
				3'h3: rdat = 7'b1111111;
				3'h4: rdat = 7'b0111111;
				3'h5: rdat = 7'b1111111;
				default: rdat = 7'b1111111;
			endcase
		default : rdat = 7'b1111111;
		endcase
endfunction
assign ROWS = rdat( col, page );

function [4:0] cdat;
input [2:0] col;
	case (col)
		3'h1: cdat = 5'b11110;
		3'h2: cdat = 5'b11101;
		3'h3: cdat = 5'b11011;
		3'h4: cdat = 5'b10111;
		3'h5: cdat = 5'b01111;
		default: cdat = 5'b11111;
	endcase
endfunction
assign COLS = cdat( col );

endmodule

//**********clock division circuit
module division(
	input osc,
	output clk1,
	output clk2
	);

reg [21:0] counter;//21->0.6sec
assign clk1 = counter[10];
assign clk2 = counter[21];
always @ (posedge osc) begin
	counter <= counter + 1'b1;
end

endmodule