モジュール化してみる

ただの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