411 lines
9.0 KiB
Systemverilog
411 lines
9.0 KiB
Systemverilog
`timescale 1ps / 1ps
|
|
|
|
module display(
|
|
input wire nreset,
|
|
input wire clk,
|
|
input wire [5:0] red, //
|
|
input wire [5:0] green, // current pixel
|
|
input wire [5:0] blue, //
|
|
output wire [7:0] x, // current pixel x
|
|
output wire [7:0] y, // current pixel y
|
|
output wire frame, // new frame indicator
|
|
output wire pixel, // new pixel indicator
|
|
output wire sck,
|
|
output wire cs,
|
|
output wire mosi,
|
|
output wire dc
|
|
);
|
|
|
|
localparam STATE_INIT_WAIT = 0;
|
|
localparam STATE_INIT_RESET = 1;
|
|
localparam STATE_INIT_WAIT_AFTER_RESET = 2;
|
|
localparam STATE_INIT_STOP_SLEEP = 3;
|
|
localparam STATE_INIT_WAIT_AFTER_STOP_SLEEP = 4;
|
|
localparam STATE_INIT_SET_FORMAT = 5;
|
|
localparam STATE_INIT_SET_FORMAT_PARAM1 = 6;
|
|
localparam STATE_INIT_WAIT_AFTER_SET_FORMAT = 7;
|
|
localparam STATE_INIT_SET_COLUMN_ADDRESS_RANGE = 8;
|
|
localparam STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM1 = 9;
|
|
localparam STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM2 = 10;
|
|
localparam STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM3 = 11;
|
|
localparam STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM4 = 12;
|
|
localparam STATE_INIT_SET_ROW_ADDRESS_RANGE = 13;
|
|
localparam STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM1 = 14;
|
|
localparam STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM2 = 15;
|
|
localparam STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM3 = 16;
|
|
localparam STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM4 = 17;
|
|
localparam STATE_INIT_SET_ADDRESSING_MODE = 18;
|
|
localparam STATE_INIT_SET_ADDRESSING_MODE_PARAM1 = 19;
|
|
localparam STATE_INIT_SET_DISPLAY_INVERSION = 20;
|
|
localparam STATE_INIT_SET_DISPLAY_MODE = 21;
|
|
localparam STATE_INIT_WAIT_AFTER_SET_DISPLAY_MODE = 22;
|
|
localparam STATE_INIT_TURN_ON_DISPLAY = 23;
|
|
localparam STATE_INIT_WAIT_AFTER_TURN_ON_DISPLAY = 24;
|
|
localparam STATE_SEND_DISPLAY_CONTENTS_COMMAND = 25;
|
|
localparam STATE_SEND_DISPLAY_CONTENTS_RED = 26;
|
|
localparam STATE_SEND_DISPLAY_CONTENTS_GREEN = 27;
|
|
localparam STATE_SEND_DISPLAY_CONTENTS_BLUE = 28;
|
|
|
|
wire next;
|
|
|
|
logic [7:0] spi_data_r;
|
|
logic send_data_r;
|
|
logic dc_r;
|
|
|
|
logic [20:0] wait_counter_r;
|
|
|
|
logic [4:0] state;
|
|
|
|
logic [7:0] x_r;
|
|
logic [7:0] y_r;
|
|
|
|
logic frame_r;
|
|
logic pixel_r;
|
|
|
|
spi spi_inst(
|
|
.nreset(nreset),
|
|
.clk(clk),
|
|
.data(spi_data_r),
|
|
.send_data(send_data_r),
|
|
.sck(sck),
|
|
.mosi(mosi),
|
|
.next(next)
|
|
);
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (nreset) begin
|
|
send_data_r <= 0;
|
|
frame_r <= 0;
|
|
pixel_r <= 0;
|
|
|
|
case (state)
|
|
STATE_INIT_WAIT : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
state <= STATE_INIT_RESET;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_RESET : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h01;
|
|
|
|
if (next) begin
|
|
wait_counter_r <= 150000 * 48; // 150 ms wait
|
|
state <= STATE_INIT_WAIT_AFTER_RESET;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_WAIT_AFTER_RESET : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
state <= STATE_INIT_STOP_SLEEP;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_STOP_SLEEP : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h11;
|
|
|
|
if (next) begin
|
|
wait_counter_r <= 10000 * 48; // 10 ms wait
|
|
state <= STATE_INIT_WAIT_AFTER_STOP_SLEEP;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_WAIT_AFTER_STOP_SLEEP : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
|
|
state <= STATE_INIT_SET_FORMAT;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_FORMAT : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h3A;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_FORMAT_PARAM1;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_FORMAT_PARAM1 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h06;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_WAIT_AFTER_SET_FORMAT;
|
|
wait_counter_r <= 10000 * 48; // 10ms wait
|
|
end
|
|
end
|
|
|
|
STATE_INIT_WAIT_AFTER_SET_FORMAT : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
|
|
state <= STATE_INIT_SET_COLUMN_ADDRESS_RANGE;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_COLUMN_ADDRESS_RANGE : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h2A;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM1;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM1 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h00;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM2;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM2 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h35;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM3;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM3 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h00;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM4;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_COLUMN_ADDRESS_RANGE_PARAM4 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'hBB;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ROW_ADDRESS_RANGE;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ROW_ADDRESS_RANGE : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h2B;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM1;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM1 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h00;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM2;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM2 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h28;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM3;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM3 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h01;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM4;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ROW_ADDRESS_RANGE_PARAM4 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'h17;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ADDRESSING_MODE;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ADDRESSING_MODE : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h36;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_ADDRESSING_MODE_PARAM1;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_ADDRESSING_MODE_PARAM1 : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= 8'hC0;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_DISPLAY_INVERSION;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_DISPLAY_INVERSION : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h21;
|
|
|
|
if (next) begin
|
|
state <= STATE_INIT_SET_DISPLAY_MODE;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_SET_DISPLAY_MODE : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h13;
|
|
|
|
if (next) begin
|
|
wait_counter_r <= 10000 * 48; // 10ms wait
|
|
state <= STATE_INIT_WAIT_AFTER_SET_DISPLAY_MODE;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_WAIT_AFTER_SET_DISPLAY_MODE : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
|
|
state <= STATE_INIT_TURN_ON_DISPLAY;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_TURN_ON_DISPLAY : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h29;
|
|
|
|
if (next) begin
|
|
wait_counter_r <= 10000 * 48; // 10ms wait
|
|
state <= STATE_INIT_WAIT_AFTER_TURN_ON_DISPLAY;
|
|
end
|
|
end
|
|
|
|
STATE_INIT_WAIT_AFTER_TURN_ON_DISPLAY : begin
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
|
|
if (wait_counter_r == 0) begin
|
|
wait_counter_r <= 0;
|
|
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_COMMAND;
|
|
end
|
|
end
|
|
|
|
STATE_SEND_DISPLAY_CONTENTS_COMMAND : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 0;
|
|
spi_data_r <= 8'h2C;
|
|
|
|
if (next) begin
|
|
x_r <= 0;
|
|
y_r <= 0;
|
|
wait_counter_r <= 32400; // 240 * 135
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_RED;
|
|
end
|
|
end
|
|
|
|
STATE_SEND_DISPLAY_CONTENTS_RED : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= {red, 2'b00};
|
|
|
|
if (next) begin
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_GREEN;
|
|
end
|
|
end
|
|
|
|
STATE_SEND_DISPLAY_CONTENTS_GREEN : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= {green, 2'b00};
|
|
|
|
if (next) begin
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_BLUE;
|
|
end
|
|
end
|
|
|
|
STATE_SEND_DISPLAY_CONTENTS_BLUE : begin
|
|
send_data_r <= 1;
|
|
dc_r <= 1;
|
|
spi_data_r <= {blue, 2'b00};
|
|
|
|
if (next) begin
|
|
x_r <= x_r + 1;
|
|
if (x_r == 134) begin
|
|
x_r <= 0;
|
|
y_r <= y_r + 1;
|
|
end
|
|
wait_counter_r <= wait_counter_r - 1;
|
|
if (wait_counter_r == 1) begin
|
|
frame_r <= 1;
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_COMMAND;
|
|
end else begin
|
|
pixel_r <= 1;
|
|
state <= STATE_SEND_DISPLAY_CONTENTS_RED;
|
|
end
|
|
end
|
|
end
|
|
endcase
|
|
end else begin
|
|
spi_data_r <= 0;
|
|
send_data_r <= 0;
|
|
wait_counter_r <= 10;
|
|
dc_r <= 0;
|
|
state <= STATE_INIT_WAIT;
|
|
x_r <= 0;
|
|
y_r <= 0;
|
|
frame_r <= 0;
|
|
pixel_r <= 0;
|
|
end
|
|
end
|
|
|
|
assign cs = ~send_data_r;
|
|
assign dc = dc_r;
|
|
assign x = x_r;
|
|
assign y = y_r;
|
|
assign frame = frame_r;
|
|
assign pixel = pixel_r;
|
|
|
|
endmodule
|