Initial commit
This commit is contained in:
737
source/lcd_top.sv
Normal file
737
source/lcd_top.sv
Normal file
@@ -0,0 +1,737 @@
|
||||
`timescale 1ns/100ps
|
||||
`default_nettype none
|
||||
|
||||
/* Yosys do not support SPRAM and MAC inferring */
|
||||
`define USE_SPRAM_PRIMITIVE
|
||||
`define USE_MAC_PRIMITIVE
|
||||
|
||||
module lcd_top #(parameter SPI_CLK_PERIOD = 6)
|
||||
(input logic clock,
|
||||
input logic reset,
|
||||
|
||||
output logic lcd_spi_csn_o,
|
||||
output logic lcd_spi_clk_o,
|
||||
output logic lcd_spi_dat_o,
|
||||
output logic lcd_spi_dcn_o,
|
||||
|
||||
input logic redraw_i,
|
||||
output logic done_o,
|
||||
|
||||
input logic [7:0] x_i,
|
||||
input logic [8:0] y_i,
|
||||
input logic [15:0] color_i,
|
||||
output logic [15:0] color_o,
|
||||
input logic req_i,
|
||||
output logic ack_o,
|
||||
input logic wr_i);
|
||||
|
||||
/* Display size */
|
||||
localparam DISPLAY_MEM_SIZE = 320 * 240 * 2; // 2 byte per pixel
|
||||
localparam DISPLAY_MEM_CW = $clog2(DISPLAY_MEM_SIZE);
|
||||
|
||||
/* Display x/y address width */
|
||||
localparam DISPLAY_XCW = 8,
|
||||
DISPLAY_YCW = 9;
|
||||
|
||||
/* Screen size and origin */
|
||||
localparam XSIZE = 240,
|
||||
YSIZE = 272,
|
||||
XORIG = 0,
|
||||
YORIG = 24;
|
||||
|
||||
localparam FBSIZE = XSIZE * YSIZE;
|
||||
localparam FBCW = $clog2(FBSIZE);
|
||||
|
||||
/* Drawing block size */
|
||||
localparam BLOCK_XS = 16, // must be power of 2
|
||||
BLOCK_YS = 16; // must be power of 2
|
||||
|
||||
localparam GRID_XS = XSIZE / BLOCK_XS,
|
||||
GRID_YS = YSIZE / BLOCK_YS;
|
||||
|
||||
localparam BLOCK_XS_CW = $clog2(BLOCK_XS);
|
||||
localparam BLOCK_YS_CW = $clog2(BLOCK_YS);
|
||||
|
||||
localparam GRID_XS_CW = $clog2(GRID_XS);
|
||||
localparam GRID_YS_CW = $clog2(GRID_YS);
|
||||
|
||||
localparam DFLAG_SIZE = GRID_XS * GRID_YS;
|
||||
localparam DFLAG_CW = $clog2(DFLAG_SIZE);
|
||||
|
||||
localparam BLOCK_SIZE = BLOCK_XS * BLOCK_YS;
|
||||
localparam BLOCK_CW = $clog2(BLOCK_SIZE);
|
||||
|
||||
/* --------- Drawing flags memory --------- */
|
||||
logic dflag[DFLAG_SIZE];
|
||||
logic dflag_wdata;
|
||||
logic dflag_rdata;
|
||||
logic [DFLAG_CW-1:0] dflag_waddr;
|
||||
logic [DFLAG_CW-1:0] dflag_raddr;
|
||||
logic [DFLAG_CW-1:0] dflag_int_addr; // for screen refresher
|
||||
logic [DFLAG_CW-1:0] dflag_ext_addr; // for external master
|
||||
logic dflag_wr;
|
||||
logic dflag_set;
|
||||
logic dflag_clr;
|
||||
|
||||
assign dflag_wr = dflag_set | dflag_clr;
|
||||
assign dflag_waddr = dflag_clr ? dflag_int_addr : dflag_ext_addr;
|
||||
assign dflag_raddr = dflag_int_addr;
|
||||
assign dflag_wdata = dflag_set;
|
||||
|
||||
/* Infer as sysMEM Block RAM */
|
||||
always_ff @ (posedge clock) begin
|
||||
if (dflag_wr)
|
||||
dflag[dflag_waddr] <= dflag_wdata;
|
||||
|
||||
dflag_rdata <= dflag[dflag_raddr];
|
||||
end
|
||||
|
||||
/* --------- Frame buffer RAM (one-port block RAM)--------- */
|
||||
logic [FBCW-1:0] fbaddr;
|
||||
logic [15:0] fb_rdata;
|
||||
logic [15:0] fb_wdata;
|
||||
logic fbwrite;
|
||||
|
||||
`ifdef USE_SPRAM_PRIMITIVE
|
||||
ice40_spram spram_i
|
||||
(.clock(clock),
|
||||
.addr(fbaddr),
|
||||
.data_i(fb_wdata),
|
||||
.data_o(fb_rdata),
|
||||
.wr(fbwrite));
|
||||
`else
|
||||
logic [15:0] fbram[FBSIZE];
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (fbwrite) begin
|
||||
fbram[fbaddr] <= fb_wdata;
|
||||
fb_rdata <= 'x;
|
||||
end
|
||||
else
|
||||
fb_rdata <= fbram[fbaddr];
|
||||
`endif
|
||||
|
||||
/* --------- Framebuffer arbiter --------- */
|
||||
logic [FBCW-1:0] fba_int; // Frame buffer address from refresher
|
||||
logic [FBCW-1:0] fba_ext; // Frame buffer address from client
|
||||
|
||||
logic fb_busy_int;
|
||||
logic fb_busy_ext;
|
||||
logic fb_clear;
|
||||
|
||||
assign fbaddr = fb_busy_int ? fba_int : fba_ext;
|
||||
assign color_o = fb_rdata;
|
||||
assign fb_wdata = fb_clear ? '0 : color_i;
|
||||
|
||||
enum int unsigned {
|
||||
FBST_CLEAR = 0,
|
||||
FBST_CLEAR_NEXT,
|
||||
FBST_WAIT,
|
||||
FBST_ADDR,
|
||||
FBST_READ,
|
||||
FBST_DONE
|
||||
} fbst;
|
||||
|
||||
logic [FBCW-1:0] ymult;
|
||||
logic [DFLAG_CW-1:0] fmult;
|
||||
|
||||
`ifdef USE_MAC_PRIMITIVE
|
||||
wire [31:0] ymac_o;
|
||||
wire [31:0] fmac_o;
|
||||
|
||||
ice40_mac16x16 ymac_i
|
||||
(.clock, .reset,
|
||||
.a(16'(y_i)),
|
||||
.b(16'(XSIZE)),
|
||||
.s(32'b0),
|
||||
.sub(1'b0),
|
||||
.y(ymac_o));
|
||||
|
||||
ice40_mac16x16 fmac_i
|
||||
(.clock, .reset,
|
||||
.a(16'(y_i) >> BLOCK_YS_CW),
|
||||
.b(16'(GRID_XS)),
|
||||
.s(32'b0),
|
||||
.sub(1'b0),
|
||||
.y(fmac_o));
|
||||
|
||||
assign ymult = ymac_o[FBCW-1:0];
|
||||
assign fmult = fmac_o[DFLAG_CW-1:0];
|
||||
`endif
|
||||
|
||||
always_ff @ (posedge clock, posedge reset)
|
||||
if (reset) begin
|
||||
fbst <= FBST_CLEAR;
|
||||
ack_o <= 1'b0;
|
||||
fbwrite <= 1'b0;
|
||||
fb_busy_ext <= 1'b0;
|
||||
dflag_set <= 1'b0;
|
||||
end
|
||||
else
|
||||
case (fbst)
|
||||
/* Clear frame buffer RAM */
|
||||
FBST_CLEAR: begin
|
||||
fba_ext <= '0;
|
||||
fbwrite <= 1'b1;
|
||||
fb_busy_ext <= 1'b1;
|
||||
fb_clear <= 1'b1;
|
||||
fbst <= FBST_CLEAR_NEXT;
|
||||
end
|
||||
|
||||
FBST_CLEAR_NEXT:
|
||||
if (fba_ext == (FBSIZE-1)) begin
|
||||
fbwrite <= 1'b0;
|
||||
fb_busy_ext <= 1'b0;
|
||||
fb_clear <= 1'b0;
|
||||
fbst <= FBST_WAIT;
|
||||
end
|
||||
else
|
||||
fba_ext <= fba_ext + 1'b1;
|
||||
|
||||
/* Main loop */
|
||||
FBST_WAIT:
|
||||
if (req_i && !fb_busy_int)
|
||||
if (x_i >= XSIZE || y_i >= YSIZE) begin
|
||||
ack_o <= 1'b1;
|
||||
fbst <= FBST_READ;
|
||||
end
|
||||
else begin
|
||||
|
||||
`ifndef USE_MAC_PRIMITIVE
|
||||
ymult <= y_i * XSIZE;
|
||||
fmult <= GRID_YS_CW'(y_i >> BLOCK_YS_CW) * GRID_XS;
|
||||
`endif
|
||||
fb_busy_ext <= 1'b1;
|
||||
fbst <= FBST_ADDR;
|
||||
end
|
||||
|
||||
FBST_ADDR:
|
||||
if (fb_busy_int) begin
|
||||
fbst <= FBST_WAIT;
|
||||
fb_busy_ext <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
fba_ext <= ymult + FBCW'(x_i);
|
||||
dflag_ext_addr <= fmult + DFLAG_CW'(x_i >> BLOCK_XS_CW);
|
||||
|
||||
if (wr_i) begin
|
||||
ack_o <= 1'b1;
|
||||
fbwrite <= 1'b1;
|
||||
dflag_set <= 1'b1;
|
||||
fbst <= FBST_DONE;
|
||||
end
|
||||
else
|
||||
fbst <= FBST_READ;
|
||||
end
|
||||
|
||||
FBST_READ: begin
|
||||
ack_o <= 1'b1;
|
||||
fbst <= FBST_DONE;
|
||||
end
|
||||
|
||||
FBST_DONE: begin
|
||||
fbwrite <= 1'b0;
|
||||
dflag_set <= 1'b0;
|
||||
ack_o <= 1'b0;
|
||||
fb_busy_ext <= 1'b0;
|
||||
fbst <= FBST_WAIT;
|
||||
end
|
||||
endcase
|
||||
|
||||
/* --------- Read initialization commands from file --------- */
|
||||
localparam INIT_FILE = "lcd_init.rom";
|
||||
localparam INIT_ROM_SIZE = 64;
|
||||
localparam INIT_DATA_SIZE = 61;
|
||||
localparam INIT_ROM_CW = $clog2(INIT_ROM_SIZE);
|
||||
|
||||
logic [8:0] init_rom [INIT_ROM_SIZE];
|
||||
logic [INIT_ROM_CW-1:0] init_addr;
|
||||
logic [8:0] init_data;
|
||||
|
||||
initial $readmemh(INIT_FILE, init_rom, 0, INIT_DATA_SIZE-1);
|
||||
|
||||
/* Block RAM as ROM */
|
||||
always_ff @ (posedge clock)
|
||||
init_data <= init_rom[init_addr];
|
||||
|
||||
/* --------- SPI master --------- */
|
||||
logic [7:0] spi_data;
|
||||
logic spi_push;
|
||||
logic spi_done;
|
||||
|
||||
lcd_spi #(.DATA_WIDTH(8),
|
||||
.SPI_CLK_PERIOD(SPI_CLK_PERIOD),
|
||||
.PUSH_ON_DONE(1)) spim_i
|
||||
(.clock, .reset,
|
||||
.data_i(spi_data),
|
||||
.push_i(spi_push),
|
||||
.done_o(spi_done),
|
||||
.spi_clk_o(lcd_spi_clk_o),
|
||||
.spi_dat_o(lcd_spi_dat_o));
|
||||
|
||||
/* --------- Main FSM --------- */
|
||||
`ifdef TESTBENCH
|
||||
localparam INIT_DELAY = 250;
|
||||
`else
|
||||
// localparam INIT_DELAY = 7500000;
|
||||
localparam INIT_DELAY = 250;
|
||||
`endif
|
||||
|
||||
enum int unsigned {
|
||||
ST_PREINIT_DELAY = 0, // 0
|
||||
ST_INIT_PUSH_SPI,
|
||||
ST_INIT_WAIT_SPI,
|
||||
ST_INIT_WAIT_LAST,
|
||||
ST_POSTINIT_DELAY,
|
||||
ST_DISPLAY_ON,
|
||||
ST_DISPLAY_ONW,
|
||||
ST_SCRCLR_CMD,
|
||||
ST_SCRCLR,
|
||||
ST_SCRCLR_LAST,
|
||||
ST_START_REDRAW, // 10
|
||||
ST_READ_FLAG,
|
||||
ST_CHECK_FLAG,
|
||||
ST_CLEAR_FLAG,
|
||||
ST_CADDR_CMD,
|
||||
ST_CADDR_0,
|
||||
ST_CADDR_1,
|
||||
ST_CADDR_2,
|
||||
ST_CADDR_3,
|
||||
ST_PADDR_CMD,
|
||||
ST_PADDR_0, // 20
|
||||
ST_PADDR_1,
|
||||
ST_PADDR_2,
|
||||
ST_PADDR_3,
|
||||
ST_WRITE_CMD,
|
||||
ST_WRITE_CMDW,
|
||||
ST_FB_READ,
|
||||
ST_STORE_PIXEL,
|
||||
ST_WRITE_PIXEL_H,
|
||||
ST_WRITE_PIXEL_L,
|
||||
ST_NEXT_PIXEL, // 30
|
||||
ST_NEXT_BLOCK
|
||||
} state, next;
|
||||
|
||||
always_ff @(posedge clock, posedge reset)
|
||||
if (reset) state <= ST_PREINIT_DELAY;
|
||||
else state <= next;
|
||||
|
||||
/* Pre/post init delay counter */
|
||||
localparam INIT_DELAY_CW = $clog2(INIT_DELAY);
|
||||
logic [INIT_DELAY_CW-1:0] delay_cntr;
|
||||
logic delay_cntr_incr;
|
||||
|
||||
always_ff @(posedge clock)
|
||||
delay_cntr <= (~reset && delay_cntr_incr) ?
|
||||
delay_cntr + 1'b1 : '0;
|
||||
|
||||
/* Initialization ROM address */
|
||||
logic init_addr_rst;
|
||||
logic init_addr_incr;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (reset || init_addr_rst)
|
||||
init_addr <= '0;
|
||||
else
|
||||
if (init_addr_incr)
|
||||
init_addr <= init_addr + 1'b1;
|
||||
|
||||
/* LCD chipselect */
|
||||
logic spi_disable;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (reset || spi_disable)
|
||||
lcd_spi_csn_o <= 1'b1;
|
||||
else if (spi_push)
|
||||
lcd_spi_csn_o <= 1'b0;
|
||||
|
||||
/* LCD data/command */
|
||||
logic spi_do_cmd;
|
||||
logic spi_do_data;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
// if (spi_do_cmd)
|
||||
// lcd_spi_dcn_o <= 1'b0;
|
||||
// else if (spi_do_data)
|
||||
// lcd_spi_dcn_o <= 1'b1;
|
||||
if (spi_do_cmd != spi_do_data)
|
||||
lcd_spi_dcn_o <= spi_do_data;
|
||||
|
||||
/* Redraw block coordinates */
|
||||
logic [GRID_XS_CW-1:0] bx;
|
||||
logic [DISPLAY_XCW-1:0] borigx;
|
||||
logic [DISPLAY_YCW-1:0] borigy;
|
||||
logic [DISPLAY_XCW-1:0] borigx_e;
|
||||
logic [DISPLAY_YCW-1:0] borigy_e;
|
||||
|
||||
assign borigx_e = borigx + BLOCK_XS - 1;
|
||||
assign borigy_e = borigy + BLOCK_YS - 1;
|
||||
|
||||
logic [FBCW-1:0] fbr_orig;
|
||||
|
||||
logic reset_redraw;
|
||||
logic next_block;
|
||||
logic is_last_blk;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (reset_redraw) begin
|
||||
dflag_int_addr <= '0;
|
||||
bx <= '0;
|
||||
borigx <= XORIG;
|
||||
borigy <= YORIG;
|
||||
fbr_orig <= '0;
|
||||
is_last_blk <= 1'b0;
|
||||
end
|
||||
else
|
||||
if (next_block) begin
|
||||
dflag_int_addr <= dflag_int_addr + 1'b1;
|
||||
is_last_blk <= (dflag_int_addr == DFLAG_CW'(DFLAG_SIZE-1)) ? 1'b1 : 1'b0;
|
||||
|
||||
if (bx == GRID_XS_CW'(GRID_XS - 1))
|
||||
begin
|
||||
bx <= '0;
|
||||
borigx <= XORIG;
|
||||
borigy <= borigy + BLOCK_YS;
|
||||
fbr_orig <= fbr_orig + BLOCK_XS + ((BLOCK_YS - 1) * XSIZE);
|
||||
end
|
||||
else
|
||||
begin
|
||||
bx <= bx + 1'b1;
|
||||
borigx <= borigx + BLOCK_XS;
|
||||
fbr_orig <= fbr_orig + BLOCK_XS;
|
||||
end
|
||||
end
|
||||
|
||||
/* Framebuffer handling */
|
||||
logic [BLOCK_XS_CW-1:0] px;
|
||||
logic [BLOCK_CW-1:0] pi;
|
||||
logic [15:0] pixel;
|
||||
|
||||
logic start_write;
|
||||
logic read_pixel;
|
||||
logic next_pixel;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (read_pixel)
|
||||
pixel <= fb_rdata;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (start_write) begin
|
||||
fba_int <= fbr_orig;
|
||||
px <= '0;
|
||||
pi <= '0;
|
||||
end
|
||||
else
|
||||
if (next_pixel) begin
|
||||
pi <= pi + 1'b1;
|
||||
|
||||
if (px == BLOCK_XS_CW'(BLOCK_XS-1))
|
||||
begin
|
||||
fba_int <= fba_int + XSIZE - BLOCK_XS + 1'b1;
|
||||
px <= '0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
fba_int <= fba_int + 1'b1;
|
||||
px <= px + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
/* Column/page addresses map */
|
||||
logic [15:0] caddr_b, caddr_e;
|
||||
logic [15:0] paddr_b, paddr_e;
|
||||
|
||||
assign caddr_b = { (16-DISPLAY_XCW)'('0), borigx };
|
||||
assign caddr_e = { (16-DISPLAY_XCW)'('0), borigx_e };
|
||||
assign paddr_b = { (16-DISPLAY_YCW)'('0), borigy };
|
||||
assign paddr_e = { (16-DISPLAY_YCW)'('0), borigy_e };
|
||||
|
||||
/* Clear screen pixel counter */
|
||||
logic [DISPLAY_MEM_CW-1:0] scrclr_pcntr;
|
||||
logic scrclr_incr;
|
||||
|
||||
always_ff @ (posedge clock)
|
||||
if (reset || init_addr_rst)
|
||||
scrclr_pcntr <= '0;
|
||||
else
|
||||
if (scrclr_incr)
|
||||
scrclr_pcntr <= scrclr_pcntr + 1'b1;
|
||||
|
||||
/* FSM combinational block */
|
||||
always @(*) begin
|
||||
next = state;
|
||||
|
||||
/* FSM outputs default value */
|
||||
delay_cntr_incr = 1'b0;
|
||||
init_addr_rst = 1'b0;
|
||||
init_addr_incr = 1'b0;
|
||||
scrclr_incr = 1'b0;
|
||||
spi_push = 1'b0;
|
||||
spi_data = '0;
|
||||
spi_disable = 1'b0;
|
||||
spi_do_cmd = 1'b0;
|
||||
spi_do_data = 1'b0;
|
||||
reset_redraw = 1'b0;
|
||||
dflag_clr = 1'b0;
|
||||
next_block = 1'b0;
|
||||
start_write = 1'b0;
|
||||
next_pixel = 1'b0;
|
||||
read_pixel = 1'b0;
|
||||
fb_busy_int = 1'b0;
|
||||
done_o = 1'b0;
|
||||
|
||||
case (state)
|
||||
ST_PREINIT_DELAY: begin
|
||||
delay_cntr_incr = 1'b1;
|
||||
init_addr_rst = 1'b1;
|
||||
|
||||
if (delay_cntr == INIT_DELAY)
|
||||
next = ST_INIT_PUSH_SPI;
|
||||
end
|
||||
|
||||
ST_INIT_PUSH_SPI: begin
|
||||
init_addr_incr = 1'b1;
|
||||
spi_data = init_data[7:0];
|
||||
spi_push = 1'b1;
|
||||
|
||||
{spi_do_cmd, spi_do_data}
|
||||
= init_data[8] ? 2'b01 : 2'b10;
|
||||
|
||||
if (init_addr == (INIT_DATA_SIZE-1))
|
||||
next = ST_INIT_WAIT_LAST;
|
||||
else
|
||||
next = ST_INIT_WAIT_SPI;
|
||||
end
|
||||
|
||||
ST_INIT_WAIT_SPI:
|
||||
if (spi_done)
|
||||
next = ST_INIT_PUSH_SPI;
|
||||
|
||||
ST_INIT_WAIT_LAST:
|
||||
if (spi_done)
|
||||
next = ST_POSTINIT_DELAY;
|
||||
|
||||
ST_POSTINIT_DELAY: begin
|
||||
spi_disable = 1'b1;
|
||||
delay_cntr_incr = 1'b1;
|
||||
|
||||
if (delay_cntr == INIT_DELAY)
|
||||
next = ST_DISPLAY_ON;
|
||||
end
|
||||
|
||||
ST_DISPLAY_ON: begin
|
||||
spi_data = 8'h29;
|
||||
spi_do_cmd = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_DISPLAY_ONW;
|
||||
end
|
||||
|
||||
ST_DISPLAY_ONW:
|
||||
if (spi_done) begin
|
||||
spi_disable = 1'b1;
|
||||
next = ST_SCRCLR_CMD;
|
||||
end
|
||||
|
||||
ST_SCRCLR_CMD: begin
|
||||
spi_data = 8'h2c;
|
||||
spi_do_cmd = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
next = ST_SCRCLR;
|
||||
end
|
||||
|
||||
ST_SCRCLR:
|
||||
if (spi_done) begin
|
||||
spi_data = 8'h00; //8'h32;
|
||||
spi_do_data = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
scrclr_incr = 1'b1;
|
||||
|
||||
if (scrclr_pcntr ==
|
||||
`ifdef TESTBENCH
|
||||
`ifdef VERILATOR
|
||||
(DISPLAY_MEM_SIZE - 1)
|
||||
`else
|
||||
200
|
||||
`endif
|
||||
`else
|
||||
(DISPLAY_MEM_SIZE - 1)
|
||||
`endif
|
||||
)
|
||||
next = ST_SCRCLR_LAST;
|
||||
end
|
||||
|
||||
ST_SCRCLR_LAST:
|
||||
if (spi_done)
|
||||
next = ST_START_REDRAW;
|
||||
|
||||
ST_START_REDRAW:
|
||||
if (redraw_i) begin
|
||||
spi_disable = 1'b1;
|
||||
reset_redraw = 1'b1;
|
||||
next = ST_READ_FLAG;
|
||||
end
|
||||
|
||||
ST_READ_FLAG:
|
||||
if (is_last_blk) begin
|
||||
done_o = 1'b1;
|
||||
next = ST_START_REDRAW;
|
||||
end
|
||||
else
|
||||
next = ST_CHECK_FLAG;
|
||||
|
||||
ST_CHECK_FLAG:
|
||||
if (dflag_rdata == 1'b1)
|
||||
next = ST_CLEAR_FLAG;
|
||||
else
|
||||
begin
|
||||
next_block = 1'b1;
|
||||
next = ST_READ_FLAG;
|
||||
end
|
||||
|
||||
ST_CLEAR_FLAG: begin
|
||||
dflag_clr = 1'b1;
|
||||
next = ST_CADDR_CMD;
|
||||
end
|
||||
|
||||
ST_CADDR_CMD: begin
|
||||
spi_data = 8'h2a;
|
||||
spi_do_cmd = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_CADDR_0;
|
||||
end
|
||||
|
||||
ST_CADDR_0:
|
||||
if (spi_done) begin
|
||||
spi_data = caddr_b[15:8];
|
||||
spi_do_data = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_CADDR_1;
|
||||
end
|
||||
|
||||
ST_CADDR_1:
|
||||
if (spi_done) begin
|
||||
spi_data = caddr_b[7:0];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_CADDR_2;
|
||||
end
|
||||
|
||||
ST_CADDR_2:
|
||||
if (spi_done) begin
|
||||
spi_data = caddr_e[15:8];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_CADDR_3;
|
||||
end
|
||||
|
||||
ST_CADDR_3:
|
||||
if (spi_done) begin
|
||||
spi_data = caddr_e[7:0];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_PADDR_CMD;
|
||||
end
|
||||
|
||||
ST_PADDR_CMD:
|
||||
if (spi_done) begin
|
||||
spi_data = 8'h2b;
|
||||
spi_do_cmd = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_PADDR_0;
|
||||
end
|
||||
|
||||
ST_PADDR_0:
|
||||
if (spi_done) begin
|
||||
spi_data = paddr_b[15:8];
|
||||
spi_do_data = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_PADDR_1;
|
||||
end
|
||||
|
||||
ST_PADDR_1:
|
||||
if (spi_done) begin
|
||||
spi_data = paddr_b[7:0];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_PADDR_2;
|
||||
end
|
||||
|
||||
ST_PADDR_2:
|
||||
if (spi_done) begin
|
||||
spi_data = paddr_e[15:8];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_PADDR_3;
|
||||
end
|
||||
|
||||
ST_PADDR_3:
|
||||
if (spi_done) begin
|
||||
spi_data = paddr_e[7:0];
|
||||
spi_push = 1'b1;
|
||||
|
||||
next = ST_WRITE_CMD;
|
||||
end
|
||||
|
||||
ST_WRITE_CMD:
|
||||
if (spi_done) begin
|
||||
spi_data = 8'h2c;
|
||||
spi_do_cmd = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
start_write = 1'b1;
|
||||
next = ST_WRITE_CMDW;
|
||||
end
|
||||
|
||||
ST_WRITE_CMDW:
|
||||
if (spi_done)
|
||||
next = ST_FB_READ;
|
||||
|
||||
ST_FB_READ:
|
||||
if (!fb_busy_ext) begin
|
||||
fb_busy_int = 1'b1;
|
||||
next = ST_STORE_PIXEL;
|
||||
end
|
||||
|
||||
ST_STORE_PIXEL: begin
|
||||
fb_busy_int = 1'b1;
|
||||
read_pixel = 1'b1;
|
||||
next = ST_WRITE_PIXEL_H;
|
||||
end
|
||||
|
||||
ST_WRITE_PIXEL_H: begin
|
||||
spi_data = pixel[15:8];
|
||||
spi_do_data = 1'b1;
|
||||
spi_push = 1'b1;
|
||||
next = ST_WRITE_PIXEL_L;
|
||||
end
|
||||
|
||||
ST_WRITE_PIXEL_L:
|
||||
if (spi_done) begin
|
||||
spi_data = pixel[7:0];
|
||||
spi_push = 1'b1;
|
||||
next = ST_NEXT_PIXEL;
|
||||
end
|
||||
|
||||
ST_NEXT_PIXEL:
|
||||
if (spi_done) begin
|
||||
next_pixel = 1'b1;
|
||||
|
||||
if (pi == (BLOCK_SIZE - 1))
|
||||
next = ST_NEXT_BLOCK;
|
||||
else
|
||||
next = ST_FB_READ;
|
||||
end
|
||||
|
||||
ST_NEXT_BLOCK: begin
|
||||
spi_disable = 1'b1;
|
||||
next_block = 1'b1;
|
||||
next = ST_READ_FLAG;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule // lcd_top
|
||||
Reference in New Issue
Block a user