ice-display/display.sv

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