Add spi.sv, update display.sv and top.sv

This commit is contained in:
shylie 2025-09-06 23:52:09 -04:00
parent 0485c1c845
commit fb5c786be5
5 changed files with 337 additions and 238 deletions

View File

@ -4,15 +4,18 @@ ICEPACK = icepack
DFU_UTIL = dfu-util
BIN2UF2 = bin2uf2
IVERILOG = iverilog
ICETIME = icetime
VVP = vvp
RTL = top.sv spi.sv display.sv
all: gateware.bin iverilog.vcd
all: gateware.bin
clean:
$(RM) *.json *.asc *.bin *.uf2 *.vcd *.vvp
sim: iverilog.vcd
prog: gateware.bin
$(DFU_UTIL) -d 1209:b1c0 -a 1 -D gateware.bin
@ -23,6 +26,7 @@ gateware.bin: $(RTL)
$(YOSYS) -q -p "read_verilog -sv $(RTL); synth_ice40 -top top -json $*.json"
$(NEXTPNR) -q --randomize-seed --up5k --package sg48 --pcf constraints.pcf --json $*.json --asc $*.asc
$(ICEPACK) $*.asc $@
$(ICETIME) $*.asc -mtd up5k
iverilog.vcd: testbench.sv $(RTL)
$(IVERILOG) -g2012 -Wall -o $*vvp.vvp testbench.sv $(RTL)

View File

@ -3,6 +3,13 @@
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,
@ -35,7 +42,9 @@ 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 = 26;
localparam STATE_SEND_DISPLAY_CONTENTS_RED = 26;
localparam STATE_SEND_DISPLAY_CONTENTS_GREEN = 27;
localparam STATE_SEND_DISPLAY_CONTENTS_BLUE = 28;
wire next;
@ -47,6 +56,12 @@ 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),
@ -60,6 +75,8 @@ spi spi_inst(
always_ff @(posedge clk) begin
if (nreset) begin
send_data_r <= 0;
frame_r <= 0;
pixel_r <= 0;
case (state)
STATE_INIT_WAIT : begin
@ -77,7 +94,7 @@ always_ff @(posedge clk) begin
spi_data_r <= 8'h01;
if (next) begin
wait_counter_r <= 150000 * 12; // 150 ms wait
wait_counter_r <= 150000 * 48; // 150 ms wait
state <= STATE_INIT_WAIT_AFTER_RESET;
end
end
@ -97,7 +114,7 @@ always_ff @(posedge clk) begin
spi_data_r <= 8'h11;
if (next) begin
wait_counter_r <= 10000 * 12; // 10 ms wait
wait_counter_r <= 10000 * 48; // 10 ms wait
state <= STATE_INIT_WAIT_AFTER_STOP_SLEEP;
end
end
@ -125,11 +142,11 @@ always_ff @(posedge clk) begin
STATE_INIT_SET_FORMAT_PARAM1 : begin
send_data_r <= 1;
dc_r <= 1;
spi_data_r <= 8'h66;
spi_data_r <= 8'h06;
if (next) begin
state <= STATE_INIT_WAIT_AFTER_SET_FORMAT;
wait_counter_r <= 10000 * 12; // 10ms wait
wait_counter_r <= 10000 * 48; // 10ms wait
end
end
@ -279,7 +296,7 @@ always_ff @(posedge clk) begin
spi_data_r <= 8'h13;
if (next) begin
wait_counter_r <= 10000 * 12; // 10ms wait
wait_counter_r <= 10000 * 48; // 10ms wait
state <= STATE_INIT_WAIT_AFTER_SET_DISPLAY_MODE;
end
end
@ -300,7 +317,7 @@ always_ff @(posedge clk) begin
spi_data_r <= 8'h29;
if (next) begin
wait_counter_r <= 10000 * 12; // 10ms wait
wait_counter_r <= 10000 * 48; // 10ms wait
state <= STATE_INIT_WAIT_AFTER_TURN_ON_DISPLAY;
end
end
@ -321,20 +338,51 @@ always_ff @(posedge clk) begin
spi_data_r <= 8'h2C;
if (next) begin
wait_counter_r <= 97200; // 240 * 135 * 3
state <= STATE_SEND_DISPLAY_CONTENTS;
x_r <= 0;
y_r <= 0;
wait_counter_r <= 32400; // 240 * 135
state <= STATE_SEND_DISPLAY_CONTENTS_RED;
end
end
STATE_SEND_DISPLAY_CONTENTS : begin
STATE_SEND_DISPLAY_CONTENTS_RED : begin
send_data_r <= 1;
dc_r <= 1;
spi_data_r <= 8'b11111100;
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
@ -345,10 +393,18 @@ always_ff @(posedge clk) begin
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

33
spi.sv Normal file
View File

@ -0,0 +1,33 @@
`timescale 1ps / 1ps
module spi(
input wire nreset,
input wire clk,
input wire [7:0] data,
input wire send_data,
output wire sck,
output wire mosi,
output wire next
);
logic [2:0] current_bit;
always_ff @(posedge clk) begin
if (send_data == 1) begin
current_bit <= current_bit + 1;
if (current_bit == 3'b111) begin
current_bit <= '0;
end
end
if (nreset == 1'b0) begin
current_bit <= '0;
end
end
assign mosi = send_data == 1 ? data[7 - current_bit] : 0;
assign next = current_bit == 3'b110; // one bit early to allow for a response in time
assign sck = clk;
endmodule

View File

@ -3,9 +3,6 @@
module testbench;
reg clk;
wire r;
wire g;
wire b;
wire sck;
wire mosi;
wire cs;
@ -13,9 +10,6 @@ wire dc;
top t(
.CLK(clk),
.LED_R(r),
.LED_G(g),
.LED_B(b),
.DISPLAY_SCK(sck),
.DISPLAY_MOSI(mosi),
.DISPLAY_CS(cs),

42
top.sv
View File

@ -2,24 +2,35 @@
module top(
input CLK,
output LED_R,
output LED_G,
output LED_B,
output DISPLAY_SCK,
output DISPLAY_MOSI,
output DISPLAY_CS,
output DISPLAY_DC
);
localparam N = 18;
logic [N:0] counter;
logic nreset_r = 0;
logic [5:0] red_r;
logic [5:0] green_r;
logic [5:0] blue_r;
wire frame;
wire pixel;
wire [7:0] x;
wire [7:0] y;
logic [5:0] counter;
display display_inst(
.nreset(nreset_r),
.clk(CLK),
.red(red_r),
.green(green_r),
.blue(blue_r),
.x(x),
.y(y),
.frame(frame),
.pixel(pixel),
.sck(DISPLAY_SCK),
.cs(DISPLAY_CS),
.mosi(DISPLAY_MOSI),
@ -28,16 +39,17 @@ display display_inst(
always_ff @(posedge CLK) begin
if (nreset_r) begin
counter <= counter + 1;
if (frame) begin
counter <= counter - 1;
end
red_r <= y[7:2] + counter[5:0];
green_r <= 6'b000000;
blue_r <= 6'b000000;
end else begin
counter <= '0;
nreset_r <= 1;
end
end
assign LED_R = 1'b1;
assign LED_G = counter[N];
assign LED_B = 1'b1;
counter <= 0;
end
end
endmodule