{gallery}Vivado project creation |
---|
|
|
|
|
|
-
CS - chip select (CSX)
-
RS - register select (D/CX)
-
CLK - spi clock (SCL)
-
MOSI - master output slave input (SDA)

-
When CS is high, all commands and parameters are ignored
-
We are starting the transition by holding CS in low state
-
At the next positive edge of the SCL, the oldest bit - D7 is being sampled, then on the next edge D6 etc...
-
On the last bit of the byte - D0, the driver also samples D/CX signal. Before that, D/CX is ignored.
module spi_4l_8b( input [8:0]command_tdata, input command_tvalid, output reg command_tready, output reg spi_cs, output reg spi_mosi, output spi_rs, output spi_clk, input clk, input reset ); reg data_locked = 0; reg [8:0] command = 0; reg [3:0] command_bit_counter = 7; assign spi_clk = clk; assign spi_rs = command[8]; always @(posedge clk) begin if (!reset) begin data_locked <= 0; command <= 0; command_tready <= 0; command_bit_counter <= 7; spi_cs <= 1; end else begin if (!data_locked) begin: wait_for_transaction spi_cs <= 1; if (command_tready && command_tvalid) begin command <= command_tdata; command_tready <= 0; data_locked <= 1; end else begin command_tready <= 1'b1; end end else begin spi_cs <= 0; spi_mosi <= command[command_bit_counter]; if (!command_bit_counter) begin: send_spi_data command_bit_counter <= 7; data_locked <= 0; end else begin command_bit_counter <= command_bit_counter - 1; end end end end endmodule
module spi_4l_8b_cmd_delay #(parameter delay_val = 500000)( output [8:0]out_command_tdata, output out_command_tvalid, input out_command_tready, input [8:0]in_command_tdata, input in_command_tvalid, output in_command_tready, input clk, input reset ); reg [31:0] delay_counter = 0; reg lock = 0; assign out_command_tdata = in_command_tdata; assign out_command_tvalid = in_command_tvalid && (!lock); assign in_command_tready = out_command_tready && (!lock); always @(posedge clk) begin if (!reset) begin delay_counter <=0; lock <= 0; end else begin if ( !in_command_tdata[8] && //If incoming data is command (in_command_tdata[7:0] != 8'b0010_1100) && //If command is not screen write out_command_tready && //If AXI4 transaction in_command_tvalid && //passes !lock // and IP is not already locked. ) begin lock <= 1; delay_counter <= delay_val; end else if (!delay_counter) begin lock <= 0; end if (delay_counter) begin: decrement_delay_counter delay_counter <= delay_counter - 1; end end end endmodule
-
First, after reset, initialize LCD with default values.
-
Second, send memory write command to LCD after 240x320 pixels.
-
Third, parse the incoming 8-bit stream into 9-bit SPI commands.
`define ili_NOP 8'h00 // No Operation - NOP
`define ili_SWRESET 8'h01 // Software Reset - SWRESET
`define ili_SLPOUT 8'h11 // Sleep Out
`define ili_GAMSET 8'h26 // Gamma Set
`define ili_DISPOFF 8'h28 // Display OFF
`define ili_DISPON 8'h29 // Display ON
`define ili_CASET 8'h2A // Column Address Set
`define ili_PASET 8'h2B // Page (row) Address Set
`define ili_RAMWR 8'h2C // Memory Write
`define ili_MADCTL 8'h36 // Memory Access Control
`define ili_IDMOFF 8'h38 // Idle Mode OFF
`define ili_IDMON 8'h39 // Idle Mode ON
`define ili_PIXSET 8'h3A // COLMOD: Pixel Format Set
`define ili_RAMWRCont 8'h3C // Write Memory Continue
`define ili_FRMCTR1 8'hB1 // Frame Rate Control (In Normal Mode/Full Colors)
`define ili_DISCTRL 8'hB6 // Display Function Control
`define ili_PWCTRL1 8'hC0 // Power Control 1
`define ili_PWCTRL2 8'hC1 // Power Control 2
`define ili_VMCTRL1 8'hC5 // VCOM Control 1
`define ili_VMCTRL2 8'hC7 // VCOM Control 2
`define ili_PGAMCTRL 8'hE0 // Positive Gamma Correction
`define ili_NGAMCTRL 8'hE1 // Negative Gamma Correction
`define ili_PCA 8'hCB // Power Control A
`define ili_PCB 8'hCF // Power Control B
`define ili_DTCA_ic 8'hE8 // Driver Timming Control A
`define ili_DTCB 8'hEA // Driver Timming Control B
`define ili_POSC 8'hED // Power On Sequence Control
`define ili_E3G 8'hF2 // Enable 3G
`define ili_PRC 8'hF7 // Pump Ratio Control
module spi_4l_8b_fifo
#(parameter MEMORY_LIMIT = 96) // Nb of init commands
(
input [7:0]in_command_tdata,
input in_command_tvalid,
output reg in_command_tready,
output [8:0]command_tdata,
output reg command_tvalid,
input command_tready,
output reg counter_ce,
input clk,
input reset
);
reg [8:0] memory[MEMORY_LIMIT - 1:0];
reg [18:0] memory_counter = 0;
reg [8:0] output_reg = 0;
localparam INIT = 0;
localparam NEXT_FRAME = 1;
localparam SEND_FRAME = 2;
localparam LCD_SIZE = 153600; //240x320*2 -> 2 transactions per pixel.
reg [1:0]state = INIT;
integer i;
task tft_write (input [7:0] cmd, input type);
begin
memory[i] = {type, cmd};
i = i + 1;
end
endtask
task write_data8 (input [7:0] cmd);
begin
tft_write(cmd, 1'b1);
end
endtask
task write_cmd (input [7:0] cmd);
begin
tft_write(cmd, 1'b0);
end
endtask
task write_data16(input [7:0] cmd1, input [7:0] cmd2);
begin
write_data8(cmd1);
write_data8(cmd2);
end
endtask
task delay();
begin
tft_write(8'h00, 1'b0);
end
endtask
initial begin
i = 0;
write_cmd(`ili_SWRESET);
write_cmd(`ili_NOP);
// Power Control A
write_cmd(`ili_PCA);
write_data8(8'h39);
write_data8(8'h2C);
write_data8(8'h00);
write_data8(8'h34);
write_data8(8'h02);
// Power Control B
write_cmd(`ili_PCB);
write_data8(8'h00);
write_data8(8'hC1);
write_data8(8'h30);
// Driver Timming Control A
write_cmd(`ili_DTCA_ic);
write_data8(8'h85);
write_data8(8'h00);
write_data8(8'h78);
// Driver Timming Control B
write_cmd(`ili_DTCB);
write_data8(8'h00);
write_data8(8'h00);
// Power On Sequence Control A
write_cmd(`ili_POSC);
write_data8(8'h64);
write_data8(8'h03);
write_data8(8'h12);
write_data8(8'h81);
// Pump Ratio Control
write_cmd(`ili_PRC);
write_data8(8'h20);
// Power Control 1
write_cmd(`ili_PWCTRL1);
write_data8(8'h23);
// Power Control 2
write_cmd(`ili_PWCTRL2);
write_data8(8'h10);
// VCOM Control 1
write_cmd(`ili_VMCTRL1);
write_data8(8'h3E);
write_data8(8'h28);
// VCOM Control 2
write_cmd(`ili_VMCTRL2);
write_data8(8'h86);
// Memory Access Control
write_cmd(`ili_MADCTL);
write_data8(8'hA8);
// Pixel Format Set
write_cmd(`ili_PIXSET);
write_data8(8'h55);
// Frame Rate Control
write_cmd(`ili_FRMCTR1);
write_data8(8'h00);
write_data8(8'h18);
// Display Function Control
write_cmd(`ili_DISCTRL);
write_data8(8'h08);
write_data8(8'h82);
write_data8(8'h27);
// Enable 3G
write_cmd(`ili_E3G);
write_data8(8'h00);
// Gamma Set
write_cmd(`ili_GAMSET);
write_data8(8'h01);
// Positive Gamma Correction
write_cmd(`ili_PGAMCTRL);
write_data8(8'h0F);
write_data8(8'h31);
write_data8(8'h2B);
write_data8(8'h0C);
write_data8(8'h0E);
write_data8(8'h08);
write_data8(8'h4E);
write_data8(8'hF1);
write_data8(8'h37);
write_data8(8'h07);
write_data8(8'h10);
write_data8(8'h03);
write_data8(8'h0E);
write_data8(8'h09);
write_data8(8'h00);
// Negative Gamma Correction
write_cmd(`ili_NGAMCTRL);
write_data8(8'h00);
write_data8(8'h0E);
write_data8(8'h14);
write_data8(8'h03);
write_data8(8'h11);
write_data8(8'h07);
write_data8(8'h31);
write_data8(8'hC1);
write_data8(8'h48);
write_data8(8'h08);
write_data8(8'h0F);
write_data8(8'h0C);
write_data8(8'h31);
write_data8(8'h36);
write_data8(8'h0F);
// Sleep Out
write_cmd(`ili_SLPOUT);
write_cmd(`ili_NOP);
//Display ON
write_cmd(`ili_DISPON);
write_cmd(`ili_NOP);
write_cmd(`ili_CASET);
write_data8(8'h00);
write_data8(8'h00);
write_data8(8'h01);
write_data8(8'h40);
write_cmd(`ili_PASET);
write_data8(8'h00);
write_data8(8'h00);
write_data8(8'h00);
write_data8(8'hEF);
//Init Done
end
always @(posedge clk) begin
if(!reset) begin
memory_counter <= 0;
counter_ce <= 0;
state <= INIT;
end else begin
case (state)
INIT: begin
counter_ce <= 0;
command_tvalid <= 1;
if (command_tvalid && command_tready) begin
memory_counter <= memory_counter + 1;
end
if (memory_counter == MEMORY_LIMIT) begin
state <= NEXT_FRAME;
command_tvalid <= 0;
end
end
NEXT_FRAME: begin
memory_counter <= 0;
command_tvalid <= 1;
if (command_tvalid && command_tready) begin
state <= SEND_FRAME;
command_tvalid <= 0;
counter_ce <= 1;
end
end
SEND_FRAME: begin
counter_ce <= 0;
in_command_tready <= command_tready;
command_tvalid <= in_command_tvalid;
if (in_command_tready && in_command_tvalid) begin
memory_counter <= memory_counter + 1;
end
if (memory_counter >= LCD_SIZE - 1)
state <= NEXT_FRAME;
end
default: begin
state <= INIT;
memory_counter <= 0;
end
endcase
end
end
assign command_tdata = state == INIT ? memory[memory_counter] : state == NEXT_FRAME ? {1'b0, `ili_RAMWR} : {1'b1, in_command_tdata};
endmodule

`timescale 1ns / 1ns module spi_4l_8b_tb; wire [8:0]in_command_tdata; wire in_command_tvalid; wire in_command_tready; wire [8:0]out_command_tdata; wire out_command_tvalid; wire out_command_tready; wire spi_cs; wire spi_mosi; wire spi_rs; wire spi_clk; reg clk = 0; reg reset = 0; reg [7:0] acu = 8'hFF; reg acu_vld = 1'b1; wire sink; wire counter_ce; spi_4l_8b_fifo u0_spi_4l_8b_fifo( .in_command_tdata(acu), .in_command_tvalid(acu_vld), .in_command_tready(sink), .command_tdata(in_command_tdata), .command_tvalid(in_command_tvalid), .command_tready(in_command_tready), .counter_ce(counter_ce), .clk(clk), .reset(reset) ); spi_4l_8b_cmd_delay #(.delay_val(20)) u0_spi_4l_8b_cmd_delay( .out_command_tdata(out_command_tdata), .out_command_tvalid(out_command_tvalid), .out_command_tready(out_command_tready), .in_command_tdata(in_command_tdata), .in_command_tvalid(in_command_tvalid), .in_command_tready(in_command_tready), .clk(clk), .reset(reset) ); spi_4l_8b u0_spi_4l_8b ( .command_tdata(out_command_tdata), .command_tvalid(out_command_tvalid), .command_tready(out_command_tready), .spi_cs(spi_cs), .spi_mosi(spi_mosi), .spi_rs(spi_rs), .spi_clk(spi_clk), .clk(clk), .reset(reset) ); always begin #5 clk = !clk; end initial begin #20 reset = !reset; $monitor("New data_in: %h %0t", u0_spi_4l_8b.command, $time); end endmodule
####################################################################### # Pmod #1 ####################################################################### set_property PACKAGE_PIN L14 [get_ports spi_rs] set_property IOSTANDARD LVCMOS33 [get_ports spi_rs] set_property PACKAGE_PIN K13 [get_ports spi_cs] set_property IOSTANDARD LVCMOS33 [get_ports spi_cs] set_property PACKAGE_PIN L13 [get_ports spi_mosi] set_property IOSTANDARD LVCMOS33 [get_ports spi_mosi] set_property PACKAGE_PIN N14 [get_ports spi_clk] set_property IOSTANDARD LVCMOS33 [get_ports spi_clk]
{gallery}block design |
---|
|
|
|
{gallery}Block design Ips |
---|
|
|
|
|
|
|
|
{gallery}Program minized |
---|
|
|
|
