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

オプティマイズの1600円MAX II CPLDボードにチップをはんだづけして,使えるようにして,LEDドットマトリクスを制御してみた.LEDドットマトリクスには,何年前かに何処かで買ってきた5×7ドット緑色のもの(MD0657M-G, 1.7V 10mA)を使用.ちなみに,5×7ドットだと,行列選択に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

 

Amazonで最大1500ポイントがもらえる無料体験 [12/12まで]

現在Amazonでaudible(オーディブル)の無料体験キャンペーンが行われており、プライム会員なら最大3000ポイント、会員でない方でも最大1500ポイントがもらえます。

「花火」などの小説や、英語教材などから好きなものを選んで聴くだけですので、チェックしてみてはいかがでしょうか。

 

 こんな記事も読まれています

コメントを残す