├── L0.md ├── README.md ├── commands.csv ├── flash.csv ├── img ├── cioo.wavedrom.js ├── cioo.wavedrom.svg ├── clock_modes.png ├── coo.wavedrom.js ├── coo.wavedrom.svg ├── data.wavedrom.js ├── data.wavedrom.svg ├── inst.wavedrom.js ├── inst.wavedrom.svg └── quad_spi_addr_mode.png ├── mcu.csv └── phy ├── README.md ├── mphy.v ├── phy-bd.svg ├── sphy.v └── test ├── mchip-blackice └── Makefile ├── mchip.v ├── schip-blackice └── Makefile └── schip.v /L0.md: -------------------------------------------------------------------------------- 1 | # SPI Layer-0 Spec 2 | 3 | ## Transactions 4 | 5 | L0 controller consumes 1 descriptor per transaction with the following fields: 6 | 7 | * command 8 | * code - [8] 9 | * width - [2] 0/1/2/4-bit (encoded: 0/1/2/3) 10 | * address 11 | * width - [2] 0/1/2/4-bit (encoded: 0/1/2/3) 12 | * length - [16] number of payload bytes (0..0xFFFF) 13 | * DTR - [1] STR/DTR (0/1) 14 | * request 15 | * width - [2] 0/1/2/4-bit (encoded: 0/1/2/3) 16 | * length - [16] number of payload bytes (0..0xFFFF) 17 | * DTR - [1] STR/DTR (0/1) 18 | * dummy 19 | * length - [8] (0..255) number of dummy cycles after the request 20 | * response 21 | * width - [2] 0/1/2/4-bit (encoded: 0/1/2/3) 22 | * length - [16] number of payload bytes (0..0xFFFF) 23 | * DTR - [1] STR/DTR (0/1) 24 | 25 | ### Command only 26 | 27 | ```js 28 | { 29 | command: { code: 0x00, width: 1 } 30 | } 31 | 32 | ``` 33 | ![Command only](https://rawgit.com/drom/spi/master/img/inst.wavedrom.svg) 34 | 35 | ### Command with 1-wire, 1-byte write 36 | 37 | ```js 38 | { 39 | command: { code: 0x00, width: 1 }, 40 | address: { length: 1 } 41 | } 42 | ``` 43 | ![instruction only](https://rawgit.com/drom/spi/master/img/data.wavedrom.svg) 44 | 45 | ### Instruction with 1-wire, 2-byte read 46 | 47 | ```js 48 | { 49 | instruction: 0x00, 50 | request: { length: 0 }, 51 | dummy: { length: 0 }, 52 | response: { length: 16 } 53 | } 54 | ``` 55 | ![instruction only](https://rawgit.com/drom/spi/master/img/coo.wavedrom.svg) 56 | 57 | ### Instruction, 1-wire, 1-byte write, 2-byte read 58 | 59 | ```js 60 | { 61 | instruction: 0x00, 62 | request: { length: 8 }, 63 | dummy: { length: 0 }, 64 | response: { length: 16 } 65 | } 66 | ``` 67 | 68 | ![instruction only](https://rawgit.com/drom/spi/master/img/cioo.wavedrom.svg) 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SPI 2 | Memory controller for SPI memory 3 | 4 | ## Features 5 | 6 | ### Internal interface 7 | - 8, 16, 32, 64 bit configurable 8 | - multiple initiators 9 | - configurable cache organization, entries, associativity 10 | - Boot from external memory 11 | 12 | ### External interface 13 | - single, dual and quad SPI 14 | - multiple chip support point-to-point 15 | - configurable clock phase 16 | - Execute-in-place (XIP) mode support 17 | - Double Data Rate (DDR) option 18 | - 24, 32 bit address 19 | - AutoBoot 20 | 21 | ## Supported memory ICs 22 | 23 | - Spansion [S25FL{004|008|016}K](https://www.spansion.com/Support/Datasheets/S25FL004K-016K_00.pdf) 24 | - Spansion [S25FL{116|132|164}K](http://www.spansion.com/Support/Datasheets/S25FL1-K_00.pdf) {16|32|64} Mib / 108MHz 25 | - Spansion [S25FL216K](http://www.spansion.com/Support/Datasheets/S25FL216K_00.pdf) 16 Mib / 65MHz 26 | - Spansion [S25FL{128|256}S](http://www.spansion.com/Support/Datasheets/S25FL128S_256S_00.pdf) {128|256} Mib / 133MHz 27 | - Micron [N25Q128A](http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_128mb_1_8v_65nm.pdf) 28 | - Micron [N25Q256A](http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_256mb_3v_65nm.pdf) 29 | - Windbond [W25Q20EW](https://www.winbond.com/resource-files/w25q20ew_revf%2011252015%20sfdp.pdf) 30 | - ON Semi [LE25S81A](http://www.onsemi.com/pub_link/Collateral/LE25S81A-D.PDF) 31 | - ESMT [F25D64QA](http://www.esmt.com.tw/DB/manager/upload/F25D64QA_1.pdf) 32 | - AMIC [A25LQ080](http://www.amictechnology.com/datasheets/A25LQ080.pdf) 33 | - GeneralPlus [GPR25L3203F](http://www.generalplus.com/doc/ds/GPR25L3203FV10_ds.pdf) 34 | - Macronix [MX25L4006E](http://natisbad.org/NAS4/refs/MX25L4006E_3V_4Mb_v1.4.pdf) 35 | 36 | ## Quad mode timing 37 | 38 | ![quad spi addr mode](img/quad_spi_addr_mode.png) 39 | ```js 40 | {signal: [ 41 | {name: 'SS#', wave: '10.................'}, 42 | {name: 'SCK', wave: '0.p................'}, 43 | { node: '..a.......b.....c.d'}, 44 | {name: 'IO0', wave: 'x.11101011334455==z', data: '14 10 c 8 4 0 4 0'}, 45 | {name: 'IO0', wave: 'z.........334455==z', data: '15 11 d 9 5 1 5 1'}, 46 | {name: 'IO0', wave: 'z.........334455==z', data: '16 12 e a 6 2 6 2'}, 47 | {name: 'IO0', wave: 'z.........334455==z', data: '17 13 f b 7 3 7 3', node: '..A.......B.....C.D'} 48 | ], 49 | edge: ['a<->b Instruction (EBh)', 'b<->c Address', 'c<->d Mode', 'a-A', 'b-B', 'c-C', 'd-D'], 50 | head:{tock:-2} 51 | } 52 | ``` 53 | 54 | ## Clock modes 55 | 56 | ![clock modes](img/clock_modes.png) 57 | 58 | ```js 59 | {signal: [ 60 | {name: 'mode:0, CPOL:0, CPHA:0', wave: '0.Pp......', phase: 0.5}, 61 | {name: 'mode:1, CPOL:0, CPHA:1', wave: '0p.......l'}, 62 | {name: 'mode:2, CPOL:1, CPHA:0', wave: '1.Nn......', phase: 0.5}, 63 | {name: 'mode:3, CPOL:1, CPHA:1', wave: '1n.......h'}, 64 | {name: 'SDI', wave: 'x========x', data: '7 6 5 4 3 2 1 0'}, 65 | ]} 66 | ``` 67 | -------------------------------------------------------------------------------- /commands.csv: -------------------------------------------------------------------------------- 1 | command,code,format 2 | 3 | RESET ENABLE,66, 4 | RESET MEMORY,99, 5 | 6 | READ ID,9E, 7 | READ ID,9F, 8 | MULTIPLE I/O READ ID,AF, 9 | READ SERIAL FLASH DISCOVERY PARAMETER,5A, 10 | 11 | READ,03, 12 | 4READ,13, 13 | FAST READ,0B, 14 | DUAL OUTPUT FAST READ,3B, 15 | DUAL INPUT/OUTPUT FAST READ,0B, 16 | DUAL INPUT/OUTPUT FAST READ,3B, 17 | DUAL INPUT/OUTPUT FAST READ,BB, 18 | QUAD OUTPUT FAST READ,6B, 19 | QUAD INPUT/OUTPUT FAST READ,0B, 20 | QUAD INPUT/OUTPUT FAST READ,6B, 21 | QUAD INPUT/OUTPUT FAST READ,EB, 22 | QUAD INPUT/OUTPUT OCTAL WORD READ,E3,Spansion 23 | QUAD INPUT/OUTPUT WORD READ,E7,Spansion 24 | 25 | WRITE ENABLE,06, 26 | WRITE DISABLE,04, 27 | 28 | READ STATUS REGISTER,05, 29 | READ STATUS REGISTER 2,35, 30 | WRITE STATUS REGISTER,01, 31 | READ LOCK REGISTER,E8, 32 | WRITE LOCK REGISTER,E5, 33 | READ FLAG STATUS REGISTER,70, 34 | CLEAR FLAG STATUS REGISTER,50, 35 | WRITE ENABLE STATUS REGISTER,50,Spansion 36 | READ NONVOLATILE CONFIGURATION REGISTER,B5, 37 | WRITE NONVOLATILE CONFIGURATION REGISTER,B1, 38 | READ VOLATILE CONFIGURATION REGISTER,85, 39 | WRITE VOLATILE CONFIGURATION REGISTER,81, 40 | READ ENHANCED VOLATILE CONFIGURATION REGISTER,65, 41 | WRITE ENHANCED VOLATILE CONFIGURATION REGISTER,61, 42 | 43 | PAGE PROGRAM,02, 44 | DUAL INPUT FAST PROGRAM,A2, 45 | EXTENDED DUAL INPUT FAST PROGRAM,02, 46 | EXTENDED DUAL INPUT FAST PROGRAM,A2, 47 | EXTENDED DUAL INPUT FAST PROGRAM,D2, 48 | QUAD INPUT FAST PROGRAM,32, 49 | EXTENDED QUAD INPUT FAST PROGRAM,02, 50 | EXTENDED QUAD INPUT FAST PROGRAM,32, 51 | EXTENDED QUAD INPUT FAST PROGRAM,12, 52 | 53 | SUBSECTOR ERASE,20, 54 | SECTOR ERASE,D8, 55 | BULK ERASE,C7, 56 | PROGRAM/ERASE RESUME,7A, 57 | PROGRAM/ERASE SUSPEND,75, 58 | 59 | READ OTP ARRAY,4B, 60 | PROGRAM OTP ARRAY,42, 61 | 62 | Deep power-down,B9, 63 | Release from deep power-down,AB, 64 | -------------------------------------------------------------------------------- /flash.csv: -------------------------------------------------------------------------------- 1 | Company,IC,Mb,MHz,Dual,Quad,XIP,DTR,$,URL 2 | ,,,,,,,,, 3 | Spansion,S25FL004K,,,,,,,,https://www.spansion.com/Support/Datasheets/S25FL004K-016K_00.pdf 4 | Spansion,S25FL008K,,,,,,,,https://www.spansion.com/Support/Datasheets/S25FL004K-016K_00.pdf 5 | Spansion,S25FL016K,,,,,,,,https://www.spansion.com/Support/Datasheets/S25FL004K-016K_00.pdf 6 | ,,,,,,,,, 7 | Spansion,S25FL116K,16,108,,,,,,http://www.spansion.com/Support/Datasheets/S25FL1-K_00.pdf 8 | Spansion,S25FL132K,32,108,,,,,,http://www.spansion.com/Support/Datasheets/S25FL1-K_00.pdf 9 | Spansion,S25FL164K,64,108,,,,,,http://www.spansion.com/Support/Datasheets/S25FL1-K_00.pdf 10 | ,,,,,,,,, 11 | Spansion,S25FL216K,16,65,,,,,,http://www.spansion.com/Support/Datasheets/S25FL216K_00.pdf 12 | ,,,,,,,,, 13 | Spansion,S25FL128S,128,133,,,,,,http://www.spansion.com/Support/Datasheets/S25FL128S_256S_00.pdf 14 | Spansion,S25FL256S,256,133,,,,,3.86,http://www.spansion.com/Support/Datasheets/S25FL128S_256S_00.pdf 15 | ,,,,,,,,, 16 | Cypress,S25FL127S,128,108,1,1,1,,2.25,http://www.spansion.com/Support/Datasheets/S25FL127S_00.pdf 17 | Cypress,S25FS128S,128,133,1,1,1,80,??, 18 | Cypress,S25FS256S,256,133,1,1,1,80,??, 19 | Cypress,S25FL128S,128,104,1,1,1,80,??, 20 | Cypress,S25FL256S,256,104,1,1,1,80,??, 21 | Cypress,S25FL512S,256,104,1,1,1,80,??, 22 | ,,,,,,,,, 23 | Micron,N25Q128A,128,108,1,1,1,54,1.64,http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_128mb_1_8v_65nm.pdf 24 | Micron,N25Q256A,256,108,1,1,1,54,2.74,http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_256mb_3v_65nm.pdf 25 | Micron,N25Q512A,512,108,1,1,1,54,5.2,http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_512mb_1ce_3v_65nm.pdf 26 | Micron,N25Q00AA,1024,108,1,1,1,54,9.15,http://www.micron.com/~/media/Documents/Products/Data%20Sheet/NOR%20Flash/Serial%20NOR/N25Q/n25q_1gb_3v_65nm.pdf 27 | Micron,MT25QL01GB,1024,133,1,1,1,66,??, 28 | ,,,,,,,,, 29 | Windbond,W25Q20EW,,,,,,,,https://www.winbond.com/resource-files/w25q20ew_revf%2011252015%20sfdp.pdf 30 | Windbond,W25Q128FV,128,104,1,1,,,1.52,http://www.winbond.com/resource-files/w25q128fv_revhh1_100913_website1.pdf 31 | Windbond,W25N01GV,1024,104,1,1,1,,,http://www.winbond.com/resource-files/da00-w25n01gva1.pdf 32 | ,,,,,,,,, 33 | ON Semi,LE25S81A,,,,,,,,http://www.onsemi.com/pub_link/Collateral/LE25S81A-D.PDF 34 | ESMT,F25D64QA,,,,,,,,http://www.esmt.com.tw/DB/manager/upload/F25D64QA_1.pdf 35 | AMIC,A25LQ080,,,,,,,,http://www.amictechnology.com/datasheets/A25LQ080.pdf 36 | GeneralPlus,GPR25L3203F,,,,,,,,http://www.generalplus.com/doc/ds/GPR25L3203FV10_ds.pdf 37 | ,,,,,,,,, 38 | Macronix,MX25L4006E,,,,,,,,http://natisbad.org/NAS4/refs/MX25L4006E_3V_4Mb_v1.4.pdf 39 | Macronix,MX25L12835F,128,133,1,1,,,2.7,"http://www.macronix.com/Lists/DataSheet/Attachments/3253/MX25L12835F,%203V,%20128Mb,%20v1.5.pdf" 40 | Macronix,MX25L25635F,256,133,1,1,,,4.87,http://media.digikey.com/pdf/Data%20Sheets/Macronix/MX25L25635F.pdf 41 | -------------------------------------------------------------------------------- /img/cioo.wavedrom.js: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['cmd', 3 | {name: 'd', wave: 'x3x', data: 'C' }, 4 | {name: 'q', wave: '010' }, 5 | {name: 'a', wave: '1..' } 6 | ], 7 | ['req', 8 | {name: 'd', wave: '3.x', data: 'i0', phase: -9 }, 9 | {name: 'q', wave: '1.0', phase: -9 }, 10 | {name: 'a', wave: '01.', phase: -9 } 11 | ], 12 | ['res', 13 | {name: 'd', wave: 'x.3..x....3.', data: 'o0 o1', phase: -26 }, 14 | {name: 'q', wave: '0.1..0....1.', phase: -26 }, 15 | {name: 'a', wave: '0...1.....01', phase: -26 } 16 | ], 17 | {name: 'SS#', wave: '=.0.................................'}, 18 | {name: 'SCK', wave: '=..n................................'}, 19 | {name: 'IO0', wave: 'x..4444444455555555x................', data: '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0'}, 20 | {name: 'IO1', wave: 'z..................5555555555555555x', data: '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0'}, 21 | {name: 'phase', wave: '=..=.......=.......=.......=.......=..', data: ' Instruction i0 o0 o1'} 22 | ], 23 | config: {skin: 'narrow'}, head: {tock: -1} 24 | } 25 | -------------------------------------------------------------------------------- /img/clock_modes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drom/spi/5e03038d390cd3352a2c289caeb357d1cdeb7f48/img/clock_modes.png -------------------------------------------------------------------------------- /img/coo.wavedrom.js: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['cmd', 3 | {name: 'd', wave: 'x3x', data: 'C' }, 4 | {name: 'q', wave: '010' }, 5 | {name: 'a', wave: '1..' } 6 | ], 7 | ['res', 8 | {name: 'd', wave: 'x.3..x....3.', data: 'D0 D1', phase: -18 }, 9 | {name: 'q', wave: '0.1..0....1.', phase: -18 }, 10 | {name: 'a', wave: '0...1.....01', phase: -18 } 11 | ], 12 | {name: 'SS#', wave: '=.0.........................'}, 13 | {name: 'SCK', wave: '=..n........................'}, 14 | {name: 'IO0', wave: 'x..44444444x................', data: '7 6 5 4 3 2 1 0'}, 15 | {name: 'IO1', wave: 'z..........5555555555555555x', data: '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0'}, 16 | {name: 'phase', wave: '=..=.......=.......=.......=..', data: ' Instruction D0 D1'} 17 | ], 18 | config: {skin: 'narrow'}, head: {tock: -1} 19 | } 20 | -------------------------------------------------------------------------------- /img/coo.wavedrom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -1012345678910111213141516171819202122232425262728dCqadD0D1qaSS#SCKIO076543210IO17654321076543210phaseInstructionD0D1cmdres -------------------------------------------------------------------------------- /img/data.wavedrom.js: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['cmd', 3 | {name: 'd', wave: 'x3x', data: 'C' }, 4 | {name: 'q', wave: '010' }, 5 | {name: 'a', wave: '1..' } 6 | ], 7 | ['req', 8 | {name: 'd', wave: '3.x', data: 'D0', phase: -8 }, 9 | {name: 'q', wave: '1.0', phase: -8 }, 10 | {name: 'a', wave: '01.', phase: -8 } 11 | ], 12 | {name: 'SS#', wave: '=.0.................'}, 13 | {name: 'SCK', wave: '=..n................'}, 14 | {name: 'IO0', wave: 'x..4444444455555555x', data: '7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0'}, 15 | {name: 'IO1', wave: 'z...................'}, 16 | {name: 'phase', wave: '=..=.......=.......=', data: ' instruction request'} 17 | ], 18 | head: {tock: -1} 19 | } 20 | -------------------------------------------------------------------------------- /img/data.wavedrom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -10123456789101112131415161718dCqadD0qaSS#SCKIO07654321076543210IO1phaseinstructionrequestcmdreq -------------------------------------------------------------------------------- /img/inst.wavedrom.js: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['cmd', 3 | {name: 'd', wave: 'x3x', data: 'C' }, 4 | {name: 'q', wave: '010' }, 5 | {name: 'a', wave: '1..' }, 6 | ], 7 | {name: 'SS#', wave: '=.0.........'}, 8 | {name: 'SCK', wave: '=..n........'}, 9 | {name: 'IO0', wave: 'x..44444444x', data: '7 6 5 4 3 2 1 0'}, 10 | {name: 'IO1', wave: 'z...........'}, 11 | {name: 'phase', wave: '=..=.......=', data: ' Instruction'} 12 | ], 13 | head: {tock: -1} 14 | } 15 | -------------------------------------------------------------------------------- /img/inst.wavedrom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -1012345678910dCqaSS#SCKIO076543210IO1phaseInstructioncmd -------------------------------------------------------------------------------- /img/quad_spi_addr_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drom/spi/5e03038d390cd3352a2c289caeb357d1cdeb7f48/img/quad_spi_addr_mode.png -------------------------------------------------------------------------------- /mcu.csv: -------------------------------------------------------------------------------- 1 | Vendor,Family,Core,Master,Fmax,$ 2 | STM,STM32L433xx,M4,QSPI,60,4.5 3 | -------------------------------------------------------------------------------- /phy/README.md: -------------------------------------------------------------------------------- 1 | 2 | ![E2E PHY](https://rawgit.com/drom/spi/master/phy/phy-bd.svg) 3 | -------------------------------------------------------------------------------- /phy/mphy.v: -------------------------------------------------------------------------------- 1 | module mphy ( 2 | c_ck, c_ncs, c_se, c_so, c_si, c_en, 3 | p_ck, p_ncs, p_se, p_so, p_si 4 | ); 5 | // controller side 6 | input c_ck; 7 | input c_ncs; 8 | input [3:0] c_se; 9 | input [7:0] c_so; 10 | output [7:0] c_si; 11 | // phy enable signal 12 | input c_en; 13 | 14 | // pad side 15 | output p_ck; 16 | output p_ncs; 17 | output [3:0] p_se; 18 | output [3:0] p_so; 19 | input [3:0] p_si; 20 | 21 | reg ncs; 22 | reg [3:0] se, so0, so1, so2, si0, si1, si2; 23 | 24 | // clock buffer 25 | assign p_ck = c_ck; 26 | 27 | // SPI select signal 28 | always @(posedge c_ck) if (c_en) ncs <= c_ncs; 29 | assign p_ncs = ncs; 30 | 31 | // enable output data 32 | always @(posedge c_ck) if (c_en) se <= c_se; 33 | assign p_se = se; 34 | 35 | // output data 36 | always @(posedge c_ck) if (c_en) so0 <= c_so[3:0]; 37 | always @(posedge c_ck) if (c_en) so1 <= c_so[7:4]; 38 | always @(negedge c_ck) if (c_en) so2 <= so1; 39 | assign p_so = c_ck ? so0 : so2; 40 | 41 | // input data 42 | always @(posedge c_ck) if (c_en) si0 <= p_si; 43 | always @(negedge c_ck) if (c_en) si1 <= p_si; 44 | always @(posedge c_ck) if (c_en) si2 <= si1; 45 | assign c_si = {si2, si0}; 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /phy/sphy.v: -------------------------------------------------------------------------------- 1 | module sphy ( 2 | p_ck, p_ncs, p_se, p_so, p_si, 3 | c_ck, c_en, c_se, c_so, c_si 4 | ); 5 | // pad side 6 | input p_ck; 7 | input p_ncs; 8 | output [3:0] p_se; 9 | output [3:0] p_so; 10 | input [3:0] p_si; 11 | 12 | // controller side 13 | output c_ck; 14 | output c_en; 15 | input [3:0] c_se; 16 | input [7:0] c_so; 17 | output [7:0] c_si; 18 | 19 | reg ncs; 20 | reg [3:0] se, so0, so1, so2, si0, si1, si2; 21 | 22 | // clock buffer 23 | assign c_ck = p_ck; 24 | 25 | // enable 26 | assign c_en = ~p_ncs; 27 | 28 | // enable output data 29 | always @(posedge c_ck) if (c_en) se <= c_se; 30 | assign p_se = se; 31 | 32 | // output data 33 | always @(posedge c_ck) if (c_en) so0 <= c_so[3:0]; 34 | always @(posedge c_ck) if (c_en) so1 <= c_so[7:4]; 35 | always @(negedge c_ck) if (c_en) so2 <= so1; 36 | assign p_so = c_ck ? so0 : so2; 37 | 38 | // input data 39 | always @(posedge c_ck) if (c_en) si0 <= p_si; 40 | always @(negedge c_ck) if (c_en) si1 <= p_si; 41 | always @(posedge c_ck) if (c_en) si2 <= si1; 42 | assign c_si = {si2, si0}; 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /phy/test/mchip-blackice/Makefile: -------------------------------------------------------------------------------- 1 | chip.bin: ../mchip.v ../../mphy.v 2 | yosys -q -p "read_verilog -sv ../mchip.v ; read_verilog ../../mphy.v ; synth_ice40 -blif chip.blif" 3 | arachne-pnr -d 8k -P tq144:4k --post-place-blif chip.post.blif chip.blif -o chip.asc 4 | yosys -q -o chip.post.json chip.post.blif 5 | icetime -j chip.sta.json -d hx8k chip.asc 6 | icepack chip.asc chip.bin 7 | 8 | .PHONY: upload 9 | upload: 10 | cat chip.bin >/dev/ttyUSB0 11 | 12 | .PHONY: clean 13 | clean: 14 | $(RM) -f chip.blif chip.post.blif chip.post.json chip.sta.json chip.asc chip.ex chip.bin 15 | -------------------------------------------------------------------------------- /phy/test/mchip.v: -------------------------------------------------------------------------------- 1 | module mchip ( 2 | c_ck, c_ncs, c_se, c_so, c_si, c_en, 3 | ck, ncs, sd0, sd1, sd2, sd3 4 | ); 5 | 6 | // controller side 7 | input c_ck; 8 | input c_ncs; 9 | input [3:0] c_se; 10 | input [7:0] c_so; 11 | output [7:0] c_si; 12 | // phy enable signal 13 | input c_en; 14 | 15 | // pad side 16 | output ck; 17 | output ncs; 18 | inout sd0, sd1, sd2, sd3; 19 | 20 | wire p_ck; 21 | wire p_ncs; 22 | wire [3:0] p_se; 23 | wire [3:0] p_so; 24 | wire [3:0] p_si; 25 | 26 | mphy umphy ( 27 | .c_ck(c_ck), 28 | .c_ncs(c_ncs), 29 | .c_se(c_se), 30 | .c_so(c_so), 31 | .c_si(c_si), 32 | .c_en(c_en), 33 | 34 | .p_ck(p_ck), 35 | .p_ncs(p_ncs), 36 | .p_se(p_se), 37 | .p_so(p_so), 38 | .p_si(p_si) 39 | ); 40 | 41 | assign ncs = p_ncs; 42 | assign ck = p_ck; 43 | 44 | SB_IO #( 45 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 46 | ) uQD0 ( 47 | .PACKAGE_PIN(sd0), .OUTPUT_ENABLE(p_se[0]), .D_OUT_0(p_so[0]), .D_IN_0(p_si[0]) 48 | ); 49 | 50 | SB_IO #( 51 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 52 | ) uQD1 ( 53 | .PACKAGE_PIN(sd1), .OUTPUT_ENABLE(p_se[1]), .D_OUT_0(p_so[1]), .D_IN_0(p_si[1]) 54 | ); 55 | 56 | SB_IO #( 57 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 58 | ) uQD2 ( 59 | .PACKAGE_PIN(sd2), .OUTPUT_ENABLE(p_se[2]), .D_OUT_0(p_so[2]), .D_IN_0(p_si[2]) 60 | ); 61 | 62 | SB_IO #( 63 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 64 | ) uQD3 ( 65 | .PACKAGE_PIN(sd3), .OUTPUT_ENABLE(p_se[3]), .D_OUT_0(p_so[3]), .D_IN_0(p_si[3]) 66 | ); 67 | 68 | endmodule 69 | -------------------------------------------------------------------------------- /phy/test/schip-blackice/Makefile: -------------------------------------------------------------------------------- 1 | chip.bin: ../schip.v ../../sphy.v 2 | yosys -q -p "read_verilog -sv ../schip.v ; read_verilog ../../sphy.v ; synth_ice40 -blif chip.blif" 3 | arachne-pnr -d 8k -P tq144:4k --post-place-blif chip.post.blif chip.blif -o chip.asc 4 | yosys -q -o chip.post.json chip.post.blif 5 | icetime -j chip.sta.json -d hx8k chip.asc 6 | icepack chip.asc chip.bin 7 | 8 | .PHONY: upload 9 | upload: 10 | cat chip.bin >/dev/ttyUSB0 11 | 12 | .PHONY: clean 13 | clean: 14 | $(RM) -f chip.blif chip.post.blif chip.post.json chip.sta.json chip.asc chip.ex chip.bin 15 | -------------------------------------------------------------------------------- /phy/test/schip.v: -------------------------------------------------------------------------------- 1 | module mchip ( 2 | ck, ncs, sd0, sd1, sd2, sd3, 3 | c_ck, c_en, c_se, c_so, c_si 4 | ); 5 | // pad side 6 | input ck; 7 | input ncs; 8 | inout sd0, sd1, sd2, sd3; 9 | 10 | // controller side 11 | output c_ck; 12 | output c_en; 13 | input [3:0] c_se; 14 | input [7:0] c_so; 15 | output [7:0] c_si; 16 | 17 | wire p_ck; 18 | wire p_ncs; 19 | wire [3:0] p_se; 20 | wire [3:0] p_so; 21 | wire [3:0] p_si; 22 | 23 | sphy u0 ( 24 | .p_ck (p_ck), 25 | .p_ncs (p_ncs), 26 | .p_se (p_se), 27 | .p_so (p_so), 28 | .p_si (p_si), 29 | 30 | .c_ck (c_ck), 31 | .c_en (c_en), 32 | .c_se (c_se), 33 | .c_so (c_so), 34 | .c_si (c_si) 35 | ); 36 | 37 | assign p_ncs = ncs; 38 | assign p_ck = ck; 39 | 40 | SB_IO #( 41 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 42 | ) uQD0 ( 43 | .PACKAGE_PIN(sd0), .OUTPUT_ENABLE(p_se[0]), .D_OUT_0(p_so[0]), .D_IN_0(p_si[0]) 44 | ); 45 | 46 | SB_IO #( 47 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 48 | ) uQD1 ( 49 | .PACKAGE_PIN(sd1), .OUTPUT_ENABLE(p_se[1]), .D_OUT_0(p_so[1]), .D_IN_0(p_si[1]) 50 | ); 51 | 52 | SB_IO #( 53 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 54 | ) uQD2 ( 55 | .PACKAGE_PIN(sd2), .OUTPUT_ENABLE(p_se[2]), .D_OUT_0(p_so[2]), .D_IN_0(p_si[2]) 56 | ); 57 | 58 | SB_IO #( 59 | .PIN_TYPE(6'b 1010_01), .PULLUP(1'b 0) 60 | ) uQD3 ( 61 | .PACKAGE_PIN(sd3), .OUTPUT_ENABLE(p_se[3]), .D_OUT_0(p_so[3]), .D_IN_0(p_si[3]) 62 | ); 63 | 64 | endmodule 65 | --------------------------------------------------------------------------------