モジュール化してみる
ただのFPGA勉強になっているのだけども。。。VerilogHDLも少しだけわかってきた。あたり前なんだけど、いくら言語とはいえ、結局論理回路を組んでいるので、できるモジュールはなんだかんだとICのような入出力になる。便利に使えるように、と思っても、printfみたいには用意できない。
とはいっても、モジュールそのままだとかなり使いにくいので、勝手に初期化してくれて、8文字(16桁だけど節約)の文字と、2行目に数字の16進表示ができるようなモジュールにしてみた。テキストと数字は、入力ピンを書き換えればクロックの立ち上がりで検出して勝手に書き換えてくれる。
クロックはメインから分周して10MHzくらいを供給してテストしている。
以下、(見苦しいのだけど)液晶制御モジュールを貼っておく。BUSYはみてない。decidataとかいってるけど表示は16進(力尽きた)。
まだやりはじめて2日目なので滅茶苦茶かもしれない。Interface誌に液晶制御のソース(spartan3スタータキット用で、値を常にモニタリングするもの)があったのでそれも参考にした。
なんでこんなものをわざわざ貼るのかというと、僕の感想を読んでても、なんとなく普通のソフト屋からしたらピンとこないかな、と思って。ソースみればピンとくるかもしれないかな、と(C風なので、ますますアセンブラと似たようなもんかな、と思うかもしれないけど、もっと低レベル)。もしくは、わかる人がもし通りがかったらヒントもらえたらありがたいな、と。
ちなみにリソースはこれでもう10%程度使用。うーん、このチップじゃ目的まではいけないかも。
spartan3なら最大4M(ちなみに今のは100k)ゲート。でも価格が……一番気楽に使えそうなヒューマンデータのキットで5万とかするんですけど。。
module Disp16_2(clk,reset,ascii_data,decidata,out_data,out_rs,out_e,out_rw); input [63:0] ascii_data; input [31:0] decidata; input reset; input clk; output [7:0] out_data; output out_rs; output out_e; output out_rw; wire [63:0] ascii_data; wire [31:0] decidata; reg [63:0] r_ascii_data; reg [31:0] r_decidata=0; reg [3:0] stat=0; reg [23:0] wait_counter=0; reg [23:0] waittime=0; reg r_out_e; reg r_out_rw; reg r_out_rs; reg [7:0] r_out_data; assign out_e=r_out_e; assign out_rw=r_out_rw; assign out_rs=r_out_rs; assign out_data=r_out_data; parameter S_INIT=0,S_INIT_COM=1,S_REFRESH=2, S_IDLE=3; reg [7:0] faddr; reg busy; //wait_counter及び実行ステータス制御 always @(posedge clk or posedge reset) begin if(reset)begin wait_counter <= 0; faddr <= 0; stat <= S_INIT; end else begin if(busy)begin if(wait_counter == 10)begin r_out_e <= 1'b1; end if(wait_counter == 21)begin r_out_e <= 1'b0; end if(wait_counter == waittime)begin faddr <= faddr + 1; //実行ステータス wait_counter <= 0; end else begin wait_counter <= wait_counter +1; end end case(stat) S_INIT: begin stat <= S_INIT_COM; faddr <= 0; end S_INIT_COM: begin if((!busy) && faddr > 0)begin stat <= S_REFRESH; faddr <= 0; end end S_REFRESH:begin if((!busy) && faddr > 0)begin stat <= S_IDLE; faddr <= 0; end end S_IDLE:begin if((!busy) && faddr > 0)begin stat <= S_REFRESH; faddr <= 0; end end default:begin stat <= S_INIT; wait_counter <= 0; faddr <= 0; end endcase end end always @(posedge clk) begin case(stat) S_INIT:begin busy <= 0; waittime <= 0; r_out_data <= 8'b00000000; r_out_rw <= 0; r_out_rs <= 0; r_ascii_data <= { 8{ 8'h20 } }; r_decidata <= 32'h0; end S_INIT_COM:begin case(faddr) 0: begin busy <= 1; r_out_data <= 8'b00000000; r_out_rw <= 1'b0; r_out_rs <= 1'b0; waittime <= 200000; end 1: begin r_out_data <= 8'b00110000; waittime <= 100000; end 2: begin r_out_data <= 8'b00110000; waittime <= 20000; end 3: begin r_out_data <= 8'b00110000; waittime <= 1000; end 4: begin r_out_data <= 8'b00111000; end 5: begin r_out_data <= 8'b00001000; end 6: begin r_out_data <= 8'b00000001; end 7: begin r_out_data <= 8'b00000110; end 8: begin busy <= 0; waittime <= 1; end default: begin busy <= 0; waittime <= 1; end endcase end S_REFRESH:begin case(faddr) 0: begin busy <= 1; r_out_data <= 8'b00001100; r_out_rw <= 1'b0; r_out_rs <= 1'b0; waittime <= 1000; end 1: begin r_out_data <= r_ascii_data[63:56]; r_out_rs <= 1'b1; end 2: begin r_out_data <= r_ascii_data[55:48]; end 3: begin r_out_data <= r_ascii_data[47:40]; end 4: begin r_out_data <= r_ascii_data[39:32]; end 5: begin r_out_data <= r_ascii_data[31:24]; end 6: begin r_out_data <= r_ascii_data[23:16]; end 7: begin r_out_data <= r_ascii_data[15:8]; end 8: begin r_out_data <= r_ascii_data[7:0]; end 9: begin r_out_data <= 8'b11000000; r_out_rs <= 1'b0; end 10: begin if(r_decidata == 32'h0)begin busy <= 0; waittime <= 1; end else begin r_out_rs <= 1'b1; r_out_data <= bintohex(r_decidata[31:28]); end end 11: begin r_out_data <= bintohex(r_decidata[27:24]); end 12: begin r_out_data <= bintohex(r_decidata[23:20]); end 13: begin r_out_data <= bintohex(r_decidata[19:16]); end 14: begin r_out_data <= bintohex(r_decidata[15:12]); end 15: begin r_out_data <= bintohex(r_decidata[11:8]); end 16: begin r_out_data <= bintohex(r_decidata[7:4]); end 17: begin r_out_data <= bintohex(r_decidata[3:0]); end 18: begin busy <= 0; waittime <= 1; end default: begin busy <= 0; waittime <= 1; end endcase end S_IDLE:begin if(r_ascii_data != ascii_data || r_decidata != decidata)begin busy <= 0; r_ascii_data <= ascii_data; r_decidata <= decidata; end else begin busy <= 1; waittime <= 9; end end default:begin r_out_data <= 8'b00000000; r_out_rs <= 0; r_out_rw <= 0; busy <= 0; waittime <= 0; end endcase end function [7:0] bintohex; input [3:0] bin; case(bin) 0: bintohex = 8'h30; 1: bintohex = 8'h31; 2: bintohex = 8'h32; 3: bintohex = 8'h33; 4: bintohex = 8'h34; 5: bintohex = 8'h35; 6: bintohex = 8'h36; 7: bintohex = 8'h37; 8: bintohex = 8'h38; 9: bintohex = 8'h39; 10: bintohex = 8'h41; 11: bintohex = 8'h42; 12: bintohex = 8'h43; 13: bintohex = 8'h44; 14: bintohex = 8'h45; 15: bintohex = 8'h46; default: bintohex=8'bxxxxxxxx; endcase endfunction endmodule