added v2.0
This commit is contained in:
40
06_IO_Devices/06_LCD/Include.v
Normal file
40
06_IO_Devices/06_LCD/Include.v
Normal file
@@ -0,0 +1,40 @@
|
||||
`include "../../01_Boolean_Logic/Nand.v"
|
||||
`include "../../01_Boolean_Logic/Not.v"
|
||||
`include "../../01_Boolean_Logic/Buffer.v"
|
||||
`include "../../01_Boolean_Logic/And.v"
|
||||
`include "../../01_Boolean_Logic/Or.v"
|
||||
`include "../../01_Boolean_Logic/Xor.v"
|
||||
`include "../../01_Boolean_Logic/Mux.v"
|
||||
`include "../../01_Boolean_Logic/DMux.v"
|
||||
`include "../../01_Boolean_Logic/Not16.v"
|
||||
`include "../../01_Boolean_Logic/Buffer16.v"
|
||||
`include "../../01_Boolean_Logic/And16.v"
|
||||
`include "../../01_Boolean_Logic/Or16.v"
|
||||
`include "../../01_Boolean_Logic/Mux16.v"
|
||||
`include "../../01_Boolean_Logic/Or8Way.v"
|
||||
`include "../../01_Boolean_Logic/Mux4Way16.v"
|
||||
`include "../../01_Boolean_Logic/Mux8Way16.v"
|
||||
`include "../../01_Boolean_Logic/DMux4Way.v"
|
||||
`include "../../01_Boolean_Logic/DMux8Way.v"
|
||||
|
||||
`include "../../02_Boolean_Arithmetic/HalfAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/FullAdder.v"
|
||||
`include "../../02_Boolean_Arithmetic/Add16.v"
|
||||
`include "../../02_Boolean_Arithmetic/Inc16.v"
|
||||
`include "../../02_Boolean_Arithmetic/ALU.v"
|
||||
|
||||
`include "../../03_Sequential_Logic/DFF.v"
|
||||
`include "../../03_Sequential_Logic/Bit.v"
|
||||
`include "../../03_Sequential_Logic/Register.v"
|
||||
`include "../../03_Sequential_Logic/PC.v"
|
||||
`include "../../03_Sequential_Logic/BitShift9R.v"
|
||||
`include "../../03_Sequential_Logic/BitShift8L.v"
|
||||
|
||||
`include "../../06_IO_Devices/UartTX.v"
|
||||
`include "../../06_IO_Devices/UartRX.v"
|
||||
`include "../../06_IO_Devices/SPI.v"
|
||||
`include "../../06_IO_Devices/InOut.v"
|
||||
`include "../../06_IO_Devices/SRAM_D.v"
|
||||
`include "../../06_IO_Devices/GO.v"
|
||||
`include "../../06_IO_Devices/LCD.v"
|
||||
`include "../../06_IO_Devices/RTP.v"
|
BIN
06_IO_Devices/06_LCD/LCD.dia
Normal file
BIN
06_IO_Devices/06_LCD/LCD.dia
Normal file
Binary file not shown.
BIN
06_IO_Devices/06_LCD/LCD.png
Normal file
BIN
06_IO_Devices/06_LCD/LCD.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
50
06_IO_Devices/06_LCD/LCD_tb.gtkw
Normal file
50
06_IO_Devices/06_LCD/LCD_tb.gtkw
Normal file
@@ -0,0 +1,50 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI
|
||||
[*] Fri Dec 30 13:59:38 2022
|
||||
[*]
|
||||
[dumpfile] "/home/micha/gitlab/nand2tetris-fpga/06_IO_Devices/06_LCD/LCD_tb.vcd"
|
||||
[dumpfile_mtime] "Fri Dec 30 13:59:22 2022"
|
||||
[dumpfile_size] 258098
|
||||
[savefile] "/home/micha/gitlab/nand2tetris-fpga/06_IO_Devices/06_LCD/LCD_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1634 636
|
||||
[pos] -1 -1
|
||||
*-19.886099 213000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] LCD_tb.
|
||||
[sst_width] 281
|
||||
[signals_width] 160
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 137
|
||||
@28
|
||||
LCD_tb.clk
|
||||
@200
|
||||
-INPUT
|
||||
@28
|
||||
LCD_tb.load
|
||||
LCD_tb.load16
|
||||
@22
|
||||
LCD_tb.in[15:0]
|
||||
@200
|
||||
-OUTPUT
|
||||
@28
|
||||
LCD_tb.CSX
|
||||
LCD_tb.DCX
|
||||
LCD_tb.SDO
|
||||
LCD_tb.SCK
|
||||
(0)LCD_tb.out[15:0]
|
||||
@200
|
||||
-CMP
|
||||
@28
|
||||
LCD_tb.CSX_cmp
|
||||
LCD_tb.DCX_cmp
|
||||
LCD_tb.SDO_cmp
|
||||
@29
|
||||
LCD_tb.SCK_cmp
|
||||
@28
|
||||
LCD_tb.out_cmp
|
||||
@200
|
||||
-Test
|
||||
@28
|
||||
LCD_tb.fail
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
BIN
06_IO_Devices/06_LCD/LCD_tb.png
Normal file
BIN
06_IO_Devices/06_LCD/LCD_tb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
89
06_IO_Devices/06_LCD/LCD_tb.v
Normal file
89
06_IO_Devices/06_LCD/LCD_tb.v
Normal file
@@ -0,0 +1,89 @@
|
||||
`timescale 10ns/1ns
|
||||
`default_nettype none
|
||||
|
||||
module LCD_tb();
|
||||
|
||||
// IN,OUT
|
||||
reg clk = 0;
|
||||
reg load = 0;
|
||||
reg load16 = 0;
|
||||
reg [15:0] in = 0;
|
||||
wire [15:0] out;
|
||||
wire DCX;
|
||||
wire CSX;
|
||||
wire SDO;
|
||||
wire SCK;
|
||||
|
||||
// Part
|
||||
LCD LCD(
|
||||
.clk(clk),
|
||||
.load(load),
|
||||
.load16(load16),
|
||||
.in(in),
|
||||
.out(out),
|
||||
.DCX(DCX), //SPI-line data/command not
|
||||
.CSX(CSX), //SPI-line chip enabled not
|
||||
.SDO(SDO), //SPI-Line master out slave in
|
||||
.SCK(SCK) //SPI-clock
|
||||
);
|
||||
|
||||
// Simulate
|
||||
always #2 clk=~clk;
|
||||
wire trigger;
|
||||
assign trigger = (n==20) || (n==40) || (n==60) || (n==80) || (n==100);
|
||||
reg [1:0] xx=0;
|
||||
always @(posedge clk) begin
|
||||
in <= trigger?$random&16'h02ff:in;
|
||||
if (trigger) xx<=xx+1;
|
||||
load <= trigger&&(~xx[1]);
|
||||
load16 <= trigger&&(xx==2);
|
||||
end
|
||||
|
||||
// Compare
|
||||
reg[5:0] bits=0;
|
||||
reg d16=0;
|
||||
always @(posedge clk)
|
||||
d16 <= load16?1:(load)?0:d16;
|
||||
always @(posedge clk)
|
||||
bits <= (load&~in[8]|load16)?1:(((bits[4]&~d16)|bits[5])?0:(busy?bits+1:0));
|
||||
wire busy=|bits;
|
||||
wire out_cmp = busy;
|
||||
reg [15:0] shift=0;
|
||||
always @(posedge clk)
|
||||
shift <= (load|load16)?in:(~SCK_cmp?shift:{shift[14:0],1'b0});
|
||||
wire SCK_cmp=busy&~bits[0];
|
||||
reg ce_cmp=0;
|
||||
always @(posedge clk)
|
||||
ce_cmp<=(load|load16)?(load16|load&~in[8]):ce_cmp;
|
||||
wire CSX_cmp=~ce_cmp;
|
||||
reg DCX_cmp=0;
|
||||
always @(posedge clk)
|
||||
DCX_cmp<=load?in[9]:(load16)?1:DCX_cmp;
|
||||
wire SDO_cmp=(d16&shift[15])|(~d16&shift[7]);
|
||||
reg fail = 0;
|
||||
reg [31:0] n = 0;
|
||||
task check;
|
||||
#4
|
||||
if ((out[15]!=out_cmp)||(SDO!=SDO_cmp)||(CSX!=CSX_cmp)||(SCK!=SCK_cmp)||(DCX!=DCX_cmp))
|
||||
begin
|
||||
$display("FAIL: clk=%1b, load=%1b, in=%16b, out=%16b, DCX=%1b, CSX=%1b, SDO=%1b, SCK=%1b",clk,load,in,out,DCX,CSX,SDO,SCK);
|
||||
fail=1;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
$dumpfile("LCD_tb.vcd");
|
||||
$dumpvars(0, LCD_tb);
|
||||
|
||||
$display("------------------------");
|
||||
$display("Testbench: LCD");
|
||||
|
||||
for (n=0; n<400;n=n+1)
|
||||
check();
|
||||
|
||||
if (fail==0) $display("passed");
|
||||
$display("------------------------");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
91
06_IO_Devices/06_LCD/Readme.md
Normal file
91
06_IO_Devices/06_LCD/Readme.md
Normal file
@@ -0,0 +1,91 @@
|
||||
## 06 LCD
|
||||
|
||||
The special function register `LCD` memory mapped to addresses 4104 and 4105 enables HACK to write bytes to the LCD controller chip ILI9341V situated on MOD-LCD2.8RTP. The communication protocol is SPI with one additional wire DCX. The protocol defines transmission of 8 bit commands with DCX = 0 followed data with DCX=1. Data packets can have any length depending on the launched command.
|
||||
|
||||
### Chip specification
|
||||
|
||||
| IN/OUT | wire | function |
|
||||
| ------ | ------- | -------------------------------------------------- |
|
||||
| IN | in[7:0] | byte to be sent. |
|
||||
| IN | in[8] | =0 send byte and set CSX low |
|
||||
| IN | in[8] | =1 pull CSX high without sending byte |
|
||||
| IN | in[9] | value of DCX when transmitting a byte. |
|
||||
| IN | load | initiates the transmission of a byte, when in[8]=0 |
|
||||
| IN | load16 | initiates the transmission of 16 bit in[15:0] |
|
||||
| OUT | out[15] | =0 chip is busy, =0 ready |
|
||||
| OUT | DCX | =0 command, =1 data |
|
||||
| OUT | SDO | serial data out |
|
||||
| OUT | SCK | serial clock |
|
||||
| OUT | CSX | chip select not |
|
||||
|
||||
The special function register `LCD` communicates with ILI9341V LCD controller over 4 wire SPI.
|
||||
|
||||
When load=1 and in[8]=0 transmission of byte in[7:0] is initiated. CSX is goes low (and stays low even when transmission is completed). DCX is set to in[9]. The byte in[7:0] is send to SDO bitwise together with 8 clock signals on SCK. During transmission out[15] is 1. After 16 clock cycles transmission is completed and out[15] is set to 0.
|
||||
|
||||
When load=1 and in[8]=1 CSX goes high and DCX=in[9] without transmission of any bit.
|
||||
|
||||
When load16=1 transmission of word in[15:0] is initiated. CSX is goes low (and stays low even when transmission is completed). DCX is set to 1 (data). After 32 clock cycles transmission is completed and out[15] is set to 0.
|
||||
|
||||
### Proposed Implementation
|
||||
|
||||
Use a `Bit` to store the state (0 = ready, 1 = busy) which is output to out[15]. Another two `Bit` store the state of DCX and CSX. Use a counter `PC` to count from 0 to 15 or 31 according to load/load16. Finally we need two connected `BitShift8L`. They will be loaded with the byte in[7:0] or the word in[15:0] to be send. After 8/16 bits are transmitted the module cleares out[15].
|
||||
|
||||

|
||||
|
||||
### Memory map
|
||||
|
||||
The special function register `LCD` is mapped to memory map of HACK according to:
|
||||
|
||||
| address | I/O device | R/W | function |
|
||||
| --------- | ---------- | --- | ----------------------------------- |
|
||||
| 4104 | LCD | W | start transmittion of byte in[7:0] |
|
||||
| 4105 | LCD | W | start transmittion of word in[15:0] |
|
||||
| 4104/4105 | LCD | R | out[15]=1 busy, out[15]=0 idle |
|
||||
|
||||
### LCD in real hardware
|
||||
|
||||
The board MO-LCD2.8RTP comes with a 2.8 inch LCD screen controlled by a controller chip ILI8341V. MOD-LCD2.8RTP must be connected to iCE40HX1K-EVB with 6 jumper wire cables: +3.3V, GND plus 4 data wires according to `iCE40HX1K-EVB.pcf` (Compare with schematic [iCE40HX1K_EVB](../../doc/iCE40HX1K-EVB_Rev_B.pdf) and [MOD-LCD2.8RTP_RevB.pdf](../../doc/MOD-LCD2.8RTP_RevB.pdf).
|
||||
|
||||
```
|
||||
set_io LCD_DCX 1 # PIO3_1A connected to pin 5 of GPIO1
|
||||
set_io LCD_SDO 2 # PIO3_1B connected to pin 7 of GPIO1
|
||||
set_io LCD_SCK 3 # PIO3_2A connected to pin 9 of GPIO1
|
||||
set_io LCD_CSX 4 # PIO3_2B connected to pin 11 of GPIO1
|
||||
```
|
||||
|
||||
| wire | iCE40HX1K-EVB (GPIO1) | MOD-LCD2.8RTP (UEXT) |
|
||||
| ------- | --------------------- | -------------------- |
|
||||
| +3.3V | 3 | 1 +3.3V |
|
||||
| GND | 4 | 2 GND |
|
||||
| LCD_DCX | 5 | 7 D/C |
|
||||
| LCD_SDO | 7 | 8 MOSI |
|
||||
| LCD_SCK | 9 | 9 SCK |
|
||||
| LCD_CSX | 11 | 11 CS |
|
||||
|
||||
***
|
||||
|
||||
### Project
|
||||
|
||||
* Implement `LCD.v` and test with testbench:
|
||||
|
||||
```
|
||||
$ cd 06_LCD
|
||||
$ apio clean
|
||||
$ apio sim
|
||||
```
|
||||
|
||||
* Compare output `OUT` of special chip`LCD` with `CMP`.
|
||||
|
||||

|
||||
|
||||
* Add special function register`LCD` to `HACK` at memory addresses 4104/4105 and upload to iCE40HX1K-EVB with the bootloader boot.asm preloaded into ROM
|
||||
|
||||
```
|
||||
$ cd ../05_GO
|
||||
$ make
|
||||
$ cd ../00_HACK
|
||||
$ apio clean
|
||||
$ apio upload
|
||||
```
|
||||
|
||||
* Proceed to `07_Operating_System` and implement the driver class `Screen.jack` that sends command over `LCD` the controller chip ILI9341V on MOD-LCD2.8RTP
|
3
06_IO_Devices/06_LCD/apio.ini
Normal file
3
06_IO_Devices/06_LCD/apio.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[env]
|
||||
board = iCE40-HX1K-EVB
|
||||
|
49
06_IO_Devices/06_LCD/lcd_tb.gtkw
Normal file
49
06_IO_Devices/06_LCD/lcd_tb.gtkw
Normal file
@@ -0,0 +1,49 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.98 (w)1999-2019 BSI
|
||||
[*] Wed Jun 17 13:06:36 2020
|
||||
[*]
|
||||
[dumpfile] "/home/micha/git/gitlab/nand2tetris/12_hack-12-nand/lcd/lcd_tb.vcd"
|
||||
[dumpfile_mtime] "Wed Jun 17 13:05:40 2020"
|
||||
[dumpfile_size] 150367
|
||||
[savefile] "/home/micha/git/gitlab/nand2tetris/12_hack-12-nand/lcd/lcd_tb.gtkw"
|
||||
[timestart] 0
|
||||
[size] 1280 703
|
||||
[pos] -1 -1
|
||||
*-6.000000 230 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[treeopen] lcd_tb.
|
||||
[treeopen] lcd_tb.LCD.
|
||||
[treeopen] lcd_tb.LCD.ISC.
|
||||
[sst_width] 238
|
||||
[signals_width] 134
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 174
|
||||
@28
|
||||
lcd_tb.startD8
|
||||
lcd_tb.LCD.startD16
|
||||
@29
|
||||
lcd_tb.LCD.startC
|
||||
@22
|
||||
lcd_tb.in[15:0]
|
||||
lcd_tb.in[15:0]
|
||||
@28
|
||||
lcd_tb.clk
|
||||
@22
|
||||
lcd_tb.LCD.bitc[4:0]
|
||||
@28
|
||||
lcd_tb.LCD.spi_mosi
|
||||
lcd_tb.LCD.mosi
|
||||
lcd_tb.LCD.spi_sck
|
||||
lcd_tb.LCD.sck
|
||||
lcd_tb.LCD.spi_cen
|
||||
lcd_tb.LCD.idle
|
||||
lcd_tb.LCD.spi_cdn
|
||||
lcd_tb.LCD.dcn
|
||||
lcd_tb.LCD.clk_baud
|
||||
@22
|
||||
lcd_tb.LCD.data_r[17:0]
|
||||
@28
|
||||
lcd_tb.LCD.load
|
||||
lcd_tb.LCD.BAUDRATE.reset
|
||||
lcd_tb.LCD.SWITCH_CLOCK.out
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
Reference in New Issue
Block a user