液晶に動画を表示

移転しました。

MAX II CPLD(EPM570T100C5)を使って、SDカードに保存した無圧縮動画を液晶ZY-FGD1442701V1, ST7735に表示しました。CPLD内部クロック5.5 MHzを使って、19 fpsとなりました。SDカードSPIモードのクロックは25 MHzまで上げられますから、fpsをもっと上げることも可能と思われます。(追記 24 MHzで80 fpsでした。)SDカードの読み込み遅延を最小限とするために、SDカードアソシエーション推奨のSD Formatterでフォーマットして、マルチブロックリードで連続して読み込んでいます。液晶の方はパラレルライトなので、この程度の速度では液晶がスピードのボトルネックにはなりません。

マルチブロックリード中にCMD0を送ったところ、リセットされなかったのですが、そういうものなのでしょうか。読み込み終了処理は面倒だったので、CMD0を送る前にリードストップのCMD12を送って、リセットを行うことにしました。



カタハネopを表示。公式mpegをVirtualDubModなどを使って連番BMPにした後、スクリプトで無圧縮バイナリに変換。十分ぬめぬめ動きました。一晩中動画再生をさせてみましたが朝でも安定して再生していました。あたりまえか。

verilog HDLコードなどはこちら。500 LE。エラー処理は適当で、とりあえず動くレベルですが。

module mov(
	output CSX, CLK, DI,
	input DO, rstx,
	output LCD_RSTX, LCD_CSX, LCD_D_CX, LCD_WRX,
	output [7:0] DATA
);

//clk
wire clk_5M5;
rc_osc rc_osc( rstx, clk_5M5 );//5.5 MHz

//reg rstx;
wire en;
wire [7:0] data;

wire vs, en_dat, req;
//lcd etc.
lcdzy lcdzy( LCD_RSTX, LCD_CSX, LCD_D_CX, LCD_WRX, DATA, rstx, clk_5M5, req, en_dat, vs, data );

//wire clk;
wire clk;
assign clk = (req ? clk_5M5 : 1'b0);
//sd
sd_cont sd_cont( clk, req, CSX, CLK, DI, DO, en_dat, vs, data );

endmodule

lcdzy.v

module lcdzy(
output reg RESX, //reset
CSX, //chip select low enable
D_CX, //data / command
WRX, //write enable
output reg [7:0] DATA,
input rstx, clk,
output reg req,
input en_data, vs,
input [7:0] data_in
);

//output RDX; //-> always write
reg [3:0] state, next_st; //state reg.
reg [15:0] wait_ms;
reg [5:0] init_addr;
wire [7:0] init_in; //, data_in;
//reg [15:0] data_addr;//16 bit  7+7+1 128*128*2
reg [13:0] wait_cnt;
reg [7:0] write_data;
wire init_dcx;
reg [11:0] frame_cnt;//0xbe8 = 3048//12bit

LCD_INIT_SEQ lcd_init_seq(init_addr, init_in, init_dcx);
//LCD_DATA_SEQ lcd_data_seq(data_addr, data_in);

// BIDIRECTIONAL TRI STATE LCD DATA BUS
//assign DATA_BUS = (RDX? 8'bz: data_value);


`define LCD_IDOL 4'h0
`define LCD_INIT 4'h1
`define RESET1 4'h2
`define RESET2 4'h3
`define SLEEP_OUT 4'h4
`define DISP_ON 4'h5
`define INIT_SEQ 4'h6
`define RAM_WR 4'h7
`define DATA_REQ 4'h8
`define DATA_SEQ 4'h9
`define WRITE 4'ha
`define WRITE_ENA 4'hb
`define LCD_WAIT 4'hc
`define LCD_SOFT_RST 4'hd

`define LCD_MS_CNT 14'd5555 // 1e-3 s * 5.5e6 Hz = 5.5e3
`define FRAME_CNT_MAX 12'hbe8//12'd3048//

//clk gen -> slow enogh at 3.3 MHz
/*always @ posedge clk_3M3 or negede reset)
	if (!rst) begin
		clk_count_
		*/


//state reg
/*always @ ( posedge clk or negedge rst ) begin
	if ( !rst )
		cur_st <= INIT;
	else
		cur_st <= next_st;
end*/

//state gen
always @ ( posedge clk or negedge rstx ) begin
	if ( !rstx ) begin
		state <= `LCD_IDOL;
		wait_ms <= 16'h0;
		wait_cnt <= 1'b0;
		init_addr <= 6'h0;
		RESX <= 1'b1;
		CSX <= 1'b1;
		D_CX <= 1'b0;
		WRX <= 1'b0;
		req <= 1'b0;
		frame_cnt <= 1'b0;
	end else begin
		case ( state )
			`LCD_IDOL: begin
				next_st <= `LCD_INIT;
				state <= `LCD_WAIT;
				wait_ms <= 16'h1000;
				wait_cnt <= 1'b0;
				init_addr <= 6'h0;
				req <= 1'b0;
				RESX <= 1'b1;
				CSX <= 1'b1;
				D_CX <= 1'b0;
				WRX <= 1'b0;
				frame_cnt <= 1'b0;
			end
			`LCD_INIT: begin //wait lcd pow on
				RESX <= 1'b1;
				CSX <= 1'b1;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				state <= `LCD_WAIT;
				next_st <= `RESET1;
				wait_ms <= 6'd50;//50ms
			end
			`RESET1: begin
				RESX <= 1'b0;//RESET
				CSX <= 1'b1;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				state <= `LCD_WAIT;
				wait_ms <= 6'd1;//more than 10us
				next_st <= `RESET2;
			end
			`RESET2: begin//WAIT stable
				RESX <= 1'b1;
				CSX <= 1'b1;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				state <= `LCD_WAIT;
				wait_ms <= 7'd120;//120ms
				next_st <= `SLEEP_OUT;
			end
			`SLEEP_OUT: begin//sleep out
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				write_data <= 8'h11;
				state <= `WRITE;
				next_st <= `DISP_ON;
				wait_ms <= 7'd120;//120ms
			end
			`DISP_ON: begin//disp on
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				write_data <= 8'h29;
				state <= `WRITE;
				next_st <= `INIT_SEQ;
				wait_ms <= 7'd120;//120ms
			end
			`INIT_SEQ: begin
				if ( init_in == 8'h00
				&& init_dcx == 1'b0 ) begin //end init
					RESX <= 1'b1;
					CSX <= 1'b1;
					D_CX <= 1'b0;
					WRX <= 1'b1;
					state <= `DATA_REQ;
					init_addr <= 4'h0;
					//DATA <= 8'h00;
				end else begin
					RESX <= 1'b1;
					CSX <= 1'b0;
					D_CX <= init_dcx;
					WRX <= 1'b1;
					write_data <= init_in;
					state <= `WRITE;
					next_st <= `INIT_SEQ;
					init_addr <= init_addr + 1'b1;
				end
			end
			`DATA_REQ: begin
				req <= 1'b1;
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				if ( en_data )
					if ( vs ) begin
						if ( frame_cnt >= `FRAME_CNT_MAX ) begin
							state <= `LCD_IDOL;
							frame_cnt <= 1'b0;
						end else begin
							state <= `RAM_WR;
							frame_cnt <= frame_cnt + 1'b1;
						end
					end else
						state <= `DATA_SEQ;
				else
					state <= `DATA_REQ;
			end
			`RAM_WR: begin
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				write_data <= 8'h2c;
				state <= `WRITE;
				next_st <= `DATA_SEQ;
				wait_ms <= 1'b0;//0 ms
			end
			`DATA_SEQ: begin
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b1;
				WRX <= 1'b1;
				write_data <= data_in;
				state <= `WRITE;
				next_st <= `DATA_REQ;
			end
			`WRITE: begin
				WRX <= 1'b0;//wait 30 ns
				DATA <= write_data;
				state <= `WRITE_ENA;
			end
			`WRITE_ENA: begin
				WRX <= 1'b1;//wait 30 ns
				if (wait_ms == 0)
					state <= next_st;
				else
					state <= `LCD_WAIT;
			end
			`LCD_WAIT: begin
				if ( wait_ms > 1'b0 ) begin
					state <= `LCD_WAIT;
					if ( wait_cnt < `LCD_MS_CNT ) begin
						wait_cnt <= wait_cnt + 1'b1;
					end else begin
						wait_cnt <= 1'b0;
						wait_ms <= wait_ms - 1'b1;
					end
				end else begin
					state <= next_st;
					wait_cnt <= 1'b0;
				end
			end
			`LCD_SOFT_RST: begin //software reset
				RESX <= 1'b1;
				CSX <= 1'b0;
				D_CX <= 1'b0;
				WRX <= 1'b1;
				write_data <= 8'h01;
				state <= `WRITE;
				next_st <= `SLEEP_OUT;
				wait_ms <= 7'd120;
			end
			default: begin
				RESX <= 1'b1;
				CSX <= 1'b1;
				D_CX <= 1'b1;
				WRX <= 1'b1;
				DATA <= 8'h00;
				state = `LCD_IDOL;
			end
		endcase
	end
end

endmodule


module LCD_INIT_SEQ ( addr, out, dcx );
input [5:0] addr;
output reg [7:0] out;
output reg dcx;

always
	case ( addr )// after soft_reset, sleep_out
		6'h00: begin out <= 8'h36; dcx <= 1'b0; end//Memory data acc
		6'h01: begin out <= 8'h88; dcx <= 1'b1; end//mirror xy BGR
		6'h02: begin out <= 8'h3a; dcx <= 1'b0; end//interface
		6'h03: begin out <= 8'h05; dcx <= 1'b1; end//16bit mode
		6'h04: begin out <= 8'h2a; dcx <= 1'b0; end//column addr set
		6'h05: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h06: begin out <= 8'h02; dcx <= 1'b1; end//02h
		6'h07: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h08: begin out <= 8'h81; dcx <= 1'b1; end//81h
		6'h09: begin out <= 8'h2b; dcx <= 1'b0; end//row addr set
		6'h0a: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h0b: begin out <= 8'h03; dcx <= 1'b1; end//03h
		6'h0c: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h0d: begin out <= 8'h82; dcx <= 1'b1; end//82h
		6'h0e: begin out <= 8'hc1; dcx <= 1'b0; end//POW CTL 2 VGHH VCLL
		6'h0f: begin out <= 8'h07; dcx <= 1'b1; end//14.7V, -12.25V
		6'h10: begin out <= 8'hc5; dcx <= 1'b0; end//VCOM CTL1
		6'h11: begin out <= 8'h3c; dcx <= 1'b1; end//VCOMH
		6'h12: begin out <= 8'h4f; dcx <= 1'b1; end//VCOML
		6'h13: begin out <= 8'he0; dcx <= 1'b0; end//gamma  +
		6'h14: begin out <= 8'h06; dcx <= 1'b1; end//
		6'h15: begin out <= 8'h0e; dcx <= 1'b1; end//
		6'h16: begin out <= 8'h05; dcx <= 1'b1; end//
		6'h17: begin out <= 8'h20; dcx <= 1'b1; end//
		6'h18: begin out <= 8'h27; dcx <= 1'b1; end//
		6'h19: begin out <= 8'h23; dcx <= 1'b1; end//
		6'h1a: begin out <= 8'h1c; dcx <= 1'b1; end//
		6'h1b: begin out <= 8'h21; dcx <= 1'b1; end//
		6'h1c: begin out <= 8'h20; dcx <= 1'b1; end//
		6'h1d: begin out <= 8'h1c; dcx <= 1'b1; end//
		6'h1e: begin out <= 8'h26; dcx <= 1'b1; end//
		6'h1f: begin out <= 8'h2f; dcx <= 1'b1; end//
		6'h20: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h21: begin out <= 8'h03; dcx <= 1'b1; end//
		6'h22: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h23: begin out <= 8'h24; dcx <= 1'b1; end//
		6'h24: begin out <= 8'he1; dcx <= 1'b0; end//gamma -
		6'h25: begin out <= 8'h06; dcx <= 1'b1; end//
		6'h26: begin out <= 8'h10; dcx <= 1'b1; end//
		6'h27: begin out <= 8'h05; dcx <= 1'b1; end//
		6'h28: begin out <= 8'h21; dcx <= 1'b1; end//
		6'h29: begin out <= 8'h27; dcx <= 1'b1; end//
		6'h2a: begin out <= 8'h22; dcx <= 1'b1; end//
		6'h2b: begin out <= 8'h1c; dcx <= 1'b1; end//
		6'h2c: begin out <= 8'h21; dcx <= 1'b1; end//
		6'h2d: begin out <= 8'h1f; dcx <= 1'b1; end//
		6'h2e: begin out <= 8'h1d; dcx <= 1'b1; end//
		6'h2f: begin out <= 8'h27; dcx <= 1'b1; end//
		6'h30: begin out <= 8'h2f; dcx <= 1'b1; end//
		6'h31: begin out <= 8'h05; dcx <= 1'b1; end//
		6'h32: begin out <= 8'h03; dcx <= 1'b1; end//
		6'h33: begin out <= 8'h00; dcx <= 1'b1; end//
		6'h34: begin out <= 8'h3f; dcx <= 1'b1; end//

		default: begin out <= 8'h00; dcx <= 1'b0; end//nop -> end
	endcase
endmodule

sd_cont.v

module sd_cont(
	input clk_5M5, rstx,
	output reg CSX,
	output CLK, DI,
	input DO,
	output reg en, // enable
	output vs, // vertical sync
	output reg [7:0] out_data
);

wire [7:0] read_byte;
reg [7:0] cmd, cmd_crc, cmd_res, write_byte, req_res;
reg [31:0] cmd_addr;
wire spi_en_wr, spi_en_rd;
reg clk_400k;
reg [3:0] clk_cnt_400k;
reg [7:0] dummy_cnt;
wire clk_slow;
reg [4:0] state, state_aft_w;
reg [2:0] write_state;
reg [15:0] wait_ms, wait_cnt;
reg [4:0] ws_time_out;
reg csx, crc_cnt;
reg [8:0] rd_cnt; //9bit
reg [14:0] data_cnt;//128*128 *2 = 0h4000 *2 -> 12+2+1 = 15 bit
//assign en = 1'b0;

spi spi(csx, CLK, DO, DI, write_byte, read_byte, spi_en_wr, spi_en_rd);

`define MS_CNT ( clk_slow ? 14'd0400 : 14'd5555 ) // 1e-3 s * 5.5e6 Hz = 5.5e3
`define PON 5'h0
`define DUMMY_CLK 5'h1
`define STOP_RD 5'h2
`define SOFT_RST 5'h3
`define SOFT_RST_RES 5'h4
`define INIT 5'h5
`define INIT_RES 5'h6
`define MULTI_READ 5'h7
`define MULTI_READ_RES 5'h8
`define SINGLE_READ 5'h9
`define SINGLE_READ_RES 5'ha
`define READ_DATA_PACKET_HD 5'hb
`define READ_DATA_PACKET_BD 5'hc
`define READ_DATA_PACKET_CRC 5'hd
`define SD_IDOL 5'he
`define CMD_WRITE 5'hf
`define SD_WAIT 5'h10

`define CMD_BIT 8'b01000000
/*cmd write state*/
`define WS_CMD 3'h0
`define WS_ADDR1 3'h1
`define WS_ADDR2 3'h2
`define WS_ADDR3 3'h3
`define WS_ADDR4 3'h4
`define WS_CRC 3'h5
`define WS_FF 3'h6
`define WS_RES 3'h7


`define WS_TIME_OUT 5'h1f
`define BLOCK_SIZE 9'h1ff

//400 kHz in init 5.5e6/400e3 ~ 14
always @ ( posedge clk_5M5 or negedge rstx ) begin
	if ( !rstx ) begin
		clk_cnt_400k <= 4'h0;
		clk_400k <= 1'b0;
	end else if ( clk_cnt_400k < 4'he ) begin
		clk_cnt_400k <= clk_cnt_400k + 1'b1;
		clk_400k <= clk_400k;
	end else begin
		clk_cnt_400k <= 4'h0;
      clk_400k <= ~clk_400k;
	end
end

//clk supply to SD
assign CLK = ( state_aft_w <= `INIT ) ? clk_400k : clk_5M5;
assign clk_slow = ( state_aft_w <= `INIT );

always @ ( negedge CLK )
	CSX <= csx;

always @ ( negedge en or negedge rstx ) begin
	if ( !rstx )
		data_cnt <= 1'b0;
	else
		data_cnt <= data_cnt + 1'b1;
end

assign vs = ( data_cnt == 0 );
//jtag_probe jtag_probe({spi_en_wr, state, state_aft_w, write_state, ws_time_out, CLK});

// state, CSX, write_byte, read_byte, spi_en_wr
always @ ( posedge CLK or negedge rstx ) begin
	if ( !rstx ) begin
		state <= `PON;
		write_byte <= 8'hff;
		en <= 0;
		csx <= 1'b1;
	end else begin
		case ( state )
			`PON: begin
				csx <= 1'b1;
				state_aft_w <= `DUMMY_CLK;
				state <= `SD_WAIT;
				wait_ms <= 16'h1; // power on and wait > 1ms
				write_byte <= 8'hff;
				dummy_cnt <= 1'b0;
				en <= 0;
				rd_cnt <= 1'b0;
				wait_cnt <= 1'b0;
				write_state <= `WS_CMD;
				crc_cnt <= 1'b0;
			end
			`DUMMY_CLK: begin //dummy clock > 74 with CSX = 1, 400kHz
				csx <= 1'b1;
				if ( dummy_cnt > 8'd74 ) begin
					state <= `STOP_RD;
					dummy_cnt <= 1'b0;
				end else begin
					dummy_cnt <= dummy_cnt + 1'b1;
				end
			end
			`STOP_RD: begin// CMD12
				csx <= 1'b1;
				cmd <= 6'd12;
				cmd_addr <= 32'd0;
				cmd_crc <= 7'b0;
				state <= `CMD_WRITE;
				state_aft_w <= `SOFT_RST;
			end
			`SOFT_RST: begin// CMD0 with CSX = 0
				csx <= 1'b1;
				cmd <= 6'd0;
				cmd_addr <= 32'd0;
				cmd_crc <= 7'b1001010;
				state <= `CMD_WRITE;
				state_aft_w <= `SOFT_RST_RES;
			end
			`SOFT_RST_RES: begin
				csx <= 1'b1;
				if ( cmd_res == 8'h01 )
					state <= `INIT;
				else
					state <= `PON;
			end
			`CMD_WRITE: begin
				csx <= 1'b0;
				if ( spi_en_wr ) begin
					case ( write_state )
						`WS_CMD: begin
							write_byte <= ( cmd | `CMD_BIT );
							write_state <= `WS_ADDR1;
						end
						`WS_ADDR1: begin
							write_byte <= ( cmd_addr >> 24 );//truncate upper bits
							write_state <= `WS_ADDR2;
						end
						`WS_ADDR2: begin
							write_byte <= ( cmd_addr >> 16 );//truncate upper bits
							write_state <= `WS_ADDR3;
						end
						`WS_ADDR3: begin
							write_byte <= ( cmd_addr >> 8 );//truncate upper bits
							write_state <= `WS_ADDR4;
						end
						`WS_ADDR4: begin
							write_byte <= cmd_addr;//truncate upper bits
							write_state <= `WS_CRC;
						end
						`WS_CRC: begin
							write_byte <= (( {1'b0, cmd_crc} << 1 ) | 1'b1 );
							write_state <= `WS_FF;
						end
						`WS_FF: begin
							write_byte <= 8'hff;
							write_state <= `WS_RES;
						end
					endcase
				end else if ( spi_en_rd & ( write_state == `WS_RES ) ) begin
					if ( read_byte != 8'hff ) begin
						write_state <= `WS_CMD;
						state <= state_aft_w;
						cmd_res <= read_byte;
						ws_time_out <= 1'b0;
					end else if ( ws_time_out > `WS_TIME_OUT ) begin
						state <= `PON; //restart
						write_state <= `WS_CMD;
						ws_time_out <= 1'b0;
					end else begin
						ws_time_out <= ws_time_out + 1'b1;
						write_state <= `WS_RES;
					end
				end
			end
			`INIT: begin //cmd1
				cmd <= 6'd1;
				cmd_addr <= 32'b0;
				cmd_crc <= 7'h0;
				state <= `CMD_WRITE;
				state_aft_w <= `INIT_RES;
				csx <= 1'b1;
			end
			`INIT_RES: begin
				csx <= 1'b1;
				if ( cmd_res == 8'h00 )//ok
					state <= `MULTI_READ;
				else if ( cmd_res == 8'h01 ) //in idol state
					state <= `CMD_WRITE; //retry
				else
					state <= `PON;//restart
			end
			`MULTI_READ: begin
				csx <= 1'b1;
				cmd <= 6'd18;
				//cmd_addr <= 32'h00000000;
				cmd_addr <= 32'h00060000;//768*512
				cmd_crc <= 7'h0;
				state <= `CMD_WRITE;
				state_aft_w <= `MULTI_READ_RES;
			end
			`MULTI_READ_RES: begin
				if ( cmd_res == 8'h00 ) begin //ok
					state <= `READ_DATA_PACKET_HD;
					state_aft_w <= `READ_DATA_PACKET_HD;
				end else if ( cmd_res == 8'h01 ) //in idol state
					state <= `CMD_WRITE; //retry
				else
					state <= `PON;//restart
			end
			`SINGLE_READ: begin
				cmd <= 6'd17;
				cmd_addr <= 32'h00000000;
				cmd_crc <= 7'h0;
				state <= `CMD_WRITE;
				state_aft_w <= `SINGLE_READ_RES;
			end
			`SINGLE_READ_RES: begin
				if ( cmd_res == 8'h00 ) begin //ok
					state <= `READ_DATA_PACKET_HD;
					state_aft_w <= `SD_IDOL;
				end else if ( cmd_res == 8'h01 ) //in idol state
					state <= `CMD_WRITE; //retry
				else
					state <= `PON;//restart
			end
			`READ_DATA_PACKET_HD: begin//read 1 block = 512 bytes
				if ( spi_en_rd ) begin
					if ( read_byte == 8'hfe ) begin
						ws_time_out <= 1'b0;
						state <= `READ_DATA_PACKET_BD;
					end else if ( ws_time_out > `WS_TIME_OUT ) begin
						state <= `PON; //restart
						ws_time_out <= 1'b0;
					end else begin
						ws_time_out <= ws_time_out + 1'b1;
					end
				end
			end
			`READ_DATA_PACKET_BD: begin
				if ( spi_en_rd ) begin
					out_data <= read_byte;
					en <= 1'b1;
					rd_cnt <= rd_cnt + 1'b1;
					if ( rd_cnt == `BLOCK_SIZE ) begin
						state <= `READ_DATA_PACKET_CRC;
						rd_cnt <= 1'b0;
					end
				end else
					en <= 1'b0;
			end
			`READ_DATA_PACKET_CRC: begin
				en <= 1'b0;
				if ( spi_en_rd ) begin
					crc_cnt <= crc_cnt + 1'b1;
					if ( crc_cnt == 1'b1 )
						state <= state_aft_w;
				end
			end
			`SD_IDOL: begin
				state_aft_w <= `PON;
				state <= `SD_WAIT;
				wait_ms <= 16'd1000;
				csx <= 1'b1;
			end
			`SD_WAIT: begin
				if ( wait_ms > 1'b0 ) begin
					state <= `SD_WAIT;
					if ( wait_cnt < `MS_CNT ) begin
						wait_cnt <= wait_cnt + 1'b1;
					end else begin
						wait_cnt <= 1'b0;
						wait_ms <= wait_ms - 1'b1;
					end
				end else begin
					state <= state_aft_w;
					wait_cnt <= 1'b0;
				end
			end
			default: begin
				state <= `SD_IDOL;
			end
		endcase
	end
end
endmodule
module spi(
input csx, CLK, MISO,
output reg MOSI,
input [7:0] inbyte,
output reg [7:0] outbyte,
output en_wr, en_rd
);

reg [2:0] cnt;
assign en_wr = ( cnt == 3'b111 ) | csx;
assign en_rd = ( cnt == 3'b000 );
//reg [7:0] data_wr;

always @ ( posedge CLK ) begin
	//if ( CSX )
	//outbyte <= 8'hff;
	//else
	outbyte <= ( outbyte << 1 ) | MISO;
	//outbyte[7-cnt] <= MISO;
end

/*always @ ( negedge en_wr ) begin //polling inbyte
	data_wr <= inbyte;
end*/

always @ ( negedge CLK ) begin
	//{MOSI, data_wr} <= ( {1'b0, data_wr} << 1 );
	MOSI <= inbyte[7-cnt];
end

always @ ( posedge CLK ) begin
	if ( csx )
		cnt <= 3'h0;
	else
		cnt <= cnt + 1'b1;

end


endmodule

連番BMP(24 bit)を無圧縮RGB = 5-6-5 bitファイルにまとめるpythonスクリプト

#!/usr/bin/env python

datapos = 0x36
lastnum = 3038
outfile = "./mov.bin"
fo = open(outfile, 'wb')

for i in range(lastnum):
    filename = "../bmp/katahane_movie %07d.bmp" % ( i + 1 )
    fi = open(filename, 'rb')
    fi.seek(datapos)

    for j in range(128*128):
        b = ord(fi.read(1))
        g = ord(fi.read(1))
        r = ord(fi.read(1))
        b1 = ( r & 0b11111000 ) | ( ( g & 0b11100000 ) >> 5 ) #R5 G3
        b2 = ( ( g & 0b00011100 ) << 3 ) | ( ( b & 0b11111000 ) >> 3 )  #G3 B5
        fo.write( bytearray( [b1, b2] ) )
    fi.close

fo.close