mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2024-10-01 01:45:38 -04:00
A construction of a minimal SPI master.
- NOTE: This is an optional feature, not built by default. Not included in the tk1 for sale at Tillitis shop. - This makes it possible to interface the SPI flash onboard TKey. - To include the SPI master in the build, use `make application_fpga.bin YOSYS_FLAG=-DINCLUDE_SPI_MASTER`. Signed-off-by: Joachim Strömbergson <joachim@assured.se>
This commit is contained in:
parent
eade3e11c5
commit
3bc2453287
@ -33,6 +33,11 @@ run-make:
|
||||
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
|
||||
$(IMAGE) make clean application_fpga.bin
|
||||
|
||||
run-make-spi:
|
||||
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
|
||||
$(IMAGE) make clean application_fpga.bin YOSYS_FLAG=-DINCLUDE_SPI_MASTER
|
||||
|
||||
|
||||
run-tb:
|
||||
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
|
||||
$(IMAGE) make tb
|
||||
|
@ -68,6 +68,7 @@ VERILOG_SRCS = \
|
||||
$(P)/core/uds/rtl/uds_rom.v \
|
||||
$(P)/core/touch_sense/rtl/touch_sense.v \
|
||||
$(P)/core/tk1/rtl/tk1.v \
|
||||
$(P)/core/tk1/rtl/tk1_spi_master.v \
|
||||
$(P)/core/tk1/rtl/udi_rom.v \
|
||||
$(P)/core/uart/rtl/uart_core.v \
|
||||
$(P)/core/uart/rtl/uart_fifo.v \
|
||||
@ -236,9 +237,19 @@ tb:
|
||||
#-------------------------------------------------------------------
|
||||
# Main FPGA build flow.
|
||||
# Synthesis. Place & Route. Bitstream generation.
|
||||
#
|
||||
# To include the SPI-master, add the flag -DINCLUDE_SPI_MASTER to Yosys cmd.
|
||||
# This can, for example, be done using
|
||||
# 'make application_fpga.bin YOSYS_FLAG=-DINCLUDE_SPI_MASTER'.
|
||||
# Important: do a make clean between builds with and wihtout the SPI master.
|
||||
# Otherwise, there is a risk of unintended components persisting between
|
||||
# builds.
|
||||
#-------------------------------------------------------------------
|
||||
synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex
|
||||
$(YOSYS_PATH)yosys -v3 -l synth.log -DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \
|
||||
|
||||
YOSYS_FLAG ?=
|
||||
|
||||
synth.json: $(FPGA_SRC) $(VERILOG_SRCS) bram_fw.hex $(P)/data/uds.hex $(P)/data/udi.hex
|
||||
$(YOSYS_PATH)yosys -v3 -l synth.log $(YOSYS_FLAG) -DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \
|
||||
-DFIRMWARE_HEX=\"$(P)/bram_fw.hex\" \
|
||||
-p 'synth_ice40 -dsp -top application_fpga -json $@; write_verilog -attr2comment synth.v' \
|
||||
$(filter %.v, $^)
|
||||
|
@ -190,6 +190,60 @@ core will detect that and start flashing the status LED with a red
|
||||
light indicating that the CPU is in a trapped state and no further
|
||||
execution is possible.
|
||||
|
||||
## SPI-master
|
||||
|
||||
The TK1 includes a minimal SPI-master that provides access to the
|
||||
Winbond Flash memory mounted on the board. The SPI-master is byte
|
||||
oriented and very minimalistic.
|
||||
|
||||
In order to transfer more than a single byte, SW must read status and
|
||||
write commands needed to send a sequence of bytes. In order to read
|
||||
out a sequence of bytes from the memory, SW must send as many dummy
|
||||
bytes as the data being read from the memory.
|
||||
|
||||
The SPI-master is controlled using a few API
|
||||
addresses:
|
||||
|
||||
```
|
||||
localparam ADDR_SPI_EN = 8'h80;
|
||||
localparam ADDR_SPI_XFER = 8'h81;
|
||||
localparam ADDR_SPI_DATA = 8'h82;
|
||||
```
|
||||
|
||||
**ADDR_SPI_EN** enables and disabled the SPI-master. Writing a 0x01 will
|
||||
lower the SPI chip select to the memory. Writing a 0x00 will raise the
|
||||
chip select.
|
||||
|
||||
Writing to the **ADDR_SPI_XFER** starts a byte transfer. Reading from
|
||||
the address returns the status for the SPI-master. If the return value
|
||||
is not zero, the SPI-master is ready to send a byte.
|
||||
|
||||
**ADDR_SPI_DATA** is the address used to send and receive a byte.
|
||||
data. The least significant byte will be sent to the memory during a
|
||||
transfer. The byte returned from the memory will be presented to SW if
|
||||
the address is read after a transfer has completed.
|
||||
|
||||
The sequence of operations needed to perform is thus:
|
||||
|
||||
1. Activate the SPI-master by writing a 0x00000001 to ADDR_SPI_EN
|
||||
2. Write a byte to ADDR_SPI_DATA
|
||||
3. Read ADDR_SPI_XFER to check status. Repeat until the read
|
||||
operation returns non-zero value
|
||||
4. Write to ADDR_SPI_XFER
|
||||
5. Read ADDR_SPI_XFER to check status. Repeat until the read operation
|
||||
returns a non-zero value
|
||||
6. Read out the received byte from ADDR_SPI_DATA
|
||||
7. Repeat 2..6 as many times as needed to send a command and data to
|
||||
the memory and getting the expected status, data back.
|
||||
8. Deactivate the SPI-master by writing 0x00000000 to ADDR_SPI_EN
|
||||
|
||||
The SPI connected memory on the board is the Winbond W25Q80. For
|
||||
information about the memory including support commands and protocol,
|
||||
see the datasheet:
|
||||
|
||||
https://www.mouser.se/datasheet/2/949/w25q80dv_dl_revh_10022015-1489677.pdf
|
||||
|
||||
|
||||
## Implementation
|
||||
|
||||
The core is implemented as a single module. Future versions will
|
||||
|
@ -28,6 +28,13 @@ module tk1(
|
||||
output wire [14 : 0] ram_aslr,
|
||||
output wire [31 : 0] ram_scramble,
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
output wire spi_ss,
|
||||
output wire spi_sck,
|
||||
output wire spi_mosi,
|
||||
input wire spi_miso,
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
output wire led_r,
|
||||
output wire led_g,
|
||||
output wire led_b,
|
||||
@ -86,6 +93,11 @@ module tk1(
|
||||
localparam ADDR_CPU_MON_FIRST = 8'h61;
|
||||
localparam ADDR_CPU_MON_LAST = 8'h62;
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
localparam ADDR_SPI_EN = 8'h80;
|
||||
localparam ADDR_SPI_XFER = 8'h81;
|
||||
localparam ADDR_SPI_DATA = 8'h82;
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
localparam TK1_NAME0 = 32'h746B3120; // "tk1 "
|
||||
localparam TK1_NAME1 = 32'h6d6b6466; // "mkdf"
|
||||
@ -157,6 +169,17 @@ module tk1(
|
||||
|
||||
wire [31:0] udi_rdata;
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
reg spi_enable;
|
||||
reg spi_enable_vld;
|
||||
reg spi_start;
|
||||
reg [7 : 0] spi_tx_data;
|
||||
reg spi_tx_data_vld;
|
||||
wire spi_ready;
|
||||
wire [7 : 0] spi_rx_data;
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent connectivity for ports etc.
|
||||
//----------------------------------------------------------------
|
||||
@ -195,6 +218,26 @@ module tk1(
|
||||
);
|
||||
/* verilator lint_on PINMISSING */
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
tk1_spi_master spi_master(
|
||||
.clk(clk),
|
||||
.reset_n(reset_n),
|
||||
|
||||
.spi_ss(spi_ss),
|
||||
.spi_sck(spi_sck),
|
||||
.spi_mosi(spi_mosi),
|
||||
.spi_miso(spi_miso),
|
||||
|
||||
.spi_enable(spi_enable),
|
||||
.spi_enable_vld(spi_enable_vld),
|
||||
.spi_start(spi_start),
|
||||
.spi_tx_data(spi_tx_data),
|
||||
.spi_tx_data_vld(spi_tx_data_vld),
|
||||
.spi_rx_data(spi_rx_data),
|
||||
.spi_ready(spi_ready)
|
||||
);
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
|
||||
udi_rom rom_i(
|
||||
.addr(address[0]),
|
||||
@ -393,6 +436,15 @@ module tk1(
|
||||
tmp_read_data = 32'h0;
|
||||
tmp_ready = 1'h0;
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
spi_enable_vld = 1'h0;
|
||||
spi_start = 1'h0;
|
||||
spi_tx_data_vld = 1'h0;
|
||||
|
||||
spi_enable = write_data[0];
|
||||
spi_tx_data = write_data[7 : 0];
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
if (cs) begin
|
||||
tmp_ready = 1'h1;
|
||||
if (we) begin
|
||||
@ -460,8 +512,22 @@ module tk1(
|
||||
cpu_mon_last_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
if (address == ADDR_SPI_EN) begin
|
||||
spi_enable_vld = 1'h1;
|
||||
end
|
||||
|
||||
if (address == ADDR_SPI_XFER) begin
|
||||
spi_start = 1'h1;
|
||||
end
|
||||
|
||||
if (address == ADDR_SPI_DATA) begin
|
||||
spi_tx_data_vld = 1'h1;
|
||||
end
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
end
|
||||
else begin
|
||||
if (address == ADDR_NAME0) begin
|
||||
tmp_read_data = TK1_NAME0;
|
||||
@ -509,6 +575,17 @@ module tk1(
|
||||
tmp_read_data = udi_rdata;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
if (address == ADDR_SPI_XFER) begin
|
||||
tmp_read_data[0] = spi_ready;
|
||||
end
|
||||
|
||||
if (address == ADDR_SPI_DATA) begin
|
||||
tmp_read_data[7 : 0] = spi_rx_data;
|
||||
end
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
end
|
||||
end
|
||||
end // api
|
||||
|
327
hw/application_fpga/core/tk1/rtl/tk1_spi_master.v
Normal file
327
hw/application_fpga/core/tk1/rtl/tk1_spi_master.v
Normal file
@ -0,0 +1,327 @@
|
||||
//======================================================================
|
||||
//
|
||||
// tk1_spi_master.v
|
||||
// ----------------
|
||||
// Minimal SPI master to be integrated into the tk1 module.
|
||||
// The SPI master is able to generate a clock, and transfer,
|
||||
// exchange a single byte with the slave.
|
||||
//
|
||||
// This master is compatible with the Winbond W25Q80DV memory.
|
||||
// This means that MSB of a response from the memory is provided
|
||||
// on the falling clock edge on the LSB of the command byte, not
|
||||
// on a dummy byte. This means that the response spans the boundary
|
||||
// of the bytes, The core handles this by sampling the MISO
|
||||
// just prior to settint the positive clock flank at the start
|
||||
// of a byte transfer.
|
||||
//
|
||||
//
|
||||
// Author: Joachim Strombergson
|
||||
// Copyright (C) 2023 - Tillitis AB
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
//======================================================================
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module tk1_spi_master(
|
||||
input wire clk,
|
||||
input wire reset_n,
|
||||
|
||||
output wire spi_ss,
|
||||
output wire spi_sck,
|
||||
output wire spi_mosi,
|
||||
input wire spi_miso,
|
||||
|
||||
input wire spi_enable,
|
||||
input wire spi_enable_vld,
|
||||
input wire spi_start,
|
||||
input wire [7 : 0] spi_tx_data,
|
||||
input wire spi_tx_data_vld,
|
||||
output wire [7 : 0] spi_rx_data,
|
||||
output wire spi_ready
|
||||
);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Internal constant and parameter definitions.
|
||||
//----------------------------------------------------------------
|
||||
parameter CTRL_IDLE = 3'h0;
|
||||
parameter CTRL_POS_FLANK = 3'h1;
|
||||
parameter CTRL_WAIT_POS = 3'h2;
|
||||
parameter CTRL_NEG_FLANK = 3'h3;
|
||||
parameter CTRL_WAIT_NEG = 3'h4;
|
||||
parameter CTRL_NEXT = 3'h5;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Registers including update variables and write enable.
|
||||
//----------------------------------------------------------------
|
||||
reg spi_ss_reg;
|
||||
|
||||
reg spi_csk_reg;
|
||||
reg spi_csk_new;
|
||||
reg spi_csk_we;
|
||||
|
||||
reg [7 : 0] spi_tx_data_reg;
|
||||
reg [7 : 0] spi_tx_data_new;
|
||||
reg spi_tx_data_nxt;
|
||||
reg spi_tx_data_we;
|
||||
|
||||
reg [7 : 0] spi_rx_data_reg;
|
||||
reg [7 : 0] spi_rx_data_new;
|
||||
reg spi_rx_data_nxt;
|
||||
reg spi_rx_data_we;
|
||||
|
||||
reg spi_miso_sample_reg;
|
||||
|
||||
reg [3 : 0] spi_clk_ctr_reg;
|
||||
reg [3 : 0] spi_clk_ctr_new;
|
||||
reg spi_clk_ctr_rst;
|
||||
|
||||
reg [2 : 0] spi_bit_ctr_reg;
|
||||
reg [2 : 0] spi_bit_ctr_new;
|
||||
reg spi_bit_ctr_rst;
|
||||
reg spi_bit_ctr_inc;
|
||||
reg spi_bit_ctr_we;
|
||||
|
||||
reg spi_ready_reg;
|
||||
reg spi_ready_new;
|
||||
reg spi_ready_we;
|
||||
|
||||
reg [2 : 0] spi_ctrl_reg;
|
||||
reg [2 : 0] spi_ctrl_new;
|
||||
reg spi_ctrl_we;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Concurrent connectivity for ports etc.
|
||||
//----------------------------------------------------------------
|
||||
assign spi_ss = spi_ss_reg;
|
||||
assign spi_sck = spi_csk_reg;
|
||||
assign spi_mosi = spi_tx_data_reg[7];
|
||||
assign spi_rx_data = spi_rx_data_reg;
|
||||
assign spi_ready = spi_ready_reg;
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// reg_update
|
||||
//----------------------------------------------------------------
|
||||
always @ (posedge clk)
|
||||
begin : reg_update
|
||||
if (!reset_n) begin
|
||||
spi_ss_reg <= 1'h1;
|
||||
spi_csk_reg <= 1'h0;
|
||||
spi_miso_sample_reg <= 1'h0;
|
||||
spi_tx_data_reg <= 8'h0;
|
||||
spi_rx_data_reg <= 8'h0;
|
||||
spi_clk_ctr_reg <= 4'h0;
|
||||
spi_bit_ctr_reg <= 3'h0;
|
||||
spi_ready_reg <= 1'h1;
|
||||
spi_ctrl_reg <= CTRL_IDLE;
|
||||
end
|
||||
|
||||
else begin
|
||||
spi_miso_sample_reg <= spi_miso;
|
||||
spi_clk_ctr_reg <= spi_clk_ctr_new;
|
||||
|
||||
if (spi_enable_vld) begin
|
||||
spi_ss_reg <= ~spi_enable;
|
||||
end
|
||||
|
||||
if (spi_csk_we) begin
|
||||
spi_csk_reg <= spi_csk_new;
|
||||
end
|
||||
|
||||
if (spi_tx_data_we) begin
|
||||
spi_tx_data_reg <= spi_tx_data_new;
|
||||
end
|
||||
|
||||
if (spi_rx_data_we) begin
|
||||
spi_rx_data_reg <= spi_rx_data_new;
|
||||
end
|
||||
|
||||
if (spi_ready_we) begin
|
||||
spi_ready_reg <= spi_ready_new;
|
||||
end
|
||||
|
||||
if (spi_bit_ctr_we) begin
|
||||
spi_bit_ctr_reg <= spi_bit_ctr_new;
|
||||
end
|
||||
|
||||
if (spi_ctrl_we) begin
|
||||
spi_ctrl_reg <= spi_ctrl_new;
|
||||
end
|
||||
end
|
||||
end // reg_update
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// clk_ctr
|
||||
//
|
||||
// Continuously running clock cycle counter that can be
|
||||
// reset to zero.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : clk_ctr
|
||||
if (spi_clk_ctr_rst) begin
|
||||
spi_clk_ctr_new = 4'h0;
|
||||
end
|
||||
|
||||
else begin
|
||||
spi_clk_ctr_new = spi_clk_ctr_reg + 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// bit_ctr
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : bit_ctr
|
||||
spi_bit_ctr_new = 3'h0;
|
||||
spi_bit_ctr_we = 1'h0;
|
||||
|
||||
if (spi_bit_ctr_rst) begin
|
||||
spi_bit_ctr_new = 3'h0;
|
||||
spi_bit_ctr_we = 1'h1;
|
||||
end
|
||||
|
||||
else if (spi_bit_ctr_inc) begin
|
||||
spi_bit_ctr_new = spi_bit_ctr_reg + 1'h1;
|
||||
spi_bit_ctr_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// spi_tx_data_logic
|
||||
// Logic for the tx_data shift register.
|
||||
// Either load or shift the data register.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : spi_tx_data_logic
|
||||
spi_tx_data_new = 8'h0;
|
||||
spi_tx_data_we = 1'h0;
|
||||
|
||||
if (spi_tx_data_vld) begin
|
||||
if (spi_ready_reg) begin
|
||||
spi_tx_data_new = spi_tx_data;
|
||||
spi_tx_data_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
if (spi_tx_data_nxt) begin
|
||||
spi_tx_data_new = {spi_tx_data_reg[6 : 0], 1'h0};
|
||||
spi_tx_data_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// spi_rx_data_logic
|
||||
// Logic for the rx_data shift register.
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : spi_rx_data_logic
|
||||
spi_rx_data_new = 8'h0;
|
||||
spi_rx_data_we = 1'h0;
|
||||
|
||||
if (spi_ss) begin
|
||||
spi_rx_data_new = 8'h0;
|
||||
spi_rx_data_we = 1'h1;
|
||||
end
|
||||
|
||||
else if (spi_rx_data_nxt) begin
|
||||
spi_rx_data_new = {spi_rx_data_reg[6 : 0], spi_miso_sample_reg};
|
||||
spi_rx_data_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// spi_master_ctrl
|
||||
//----------------------------------------------------------------
|
||||
always @*
|
||||
begin : spi_master_ctrl
|
||||
spi_rx_data_nxt = 1'h0;
|
||||
spi_tx_data_nxt = 1'h0;
|
||||
spi_clk_ctr_rst = 1'h0;
|
||||
spi_csk_new = 1'h0;
|
||||
spi_csk_we = 1'h0;
|
||||
spi_bit_ctr_rst = 1'h0;
|
||||
spi_bit_ctr_inc = 1'h0;
|
||||
spi_ready_new = 1'h0;
|
||||
spi_ready_we = 1'h0;
|
||||
spi_ctrl_new = CTRL_IDLE;
|
||||
spi_ctrl_we = 1'h0;
|
||||
|
||||
|
||||
case (spi_ctrl_reg)
|
||||
CTRL_IDLE: begin
|
||||
if (spi_start) begin
|
||||
spi_csk_new = 1'h0;
|
||||
spi_csk_we = 1'h1;
|
||||
spi_bit_ctr_rst = 1'h1;
|
||||
spi_ready_new = 1'h0;
|
||||
spi_ready_we = 1'h1;
|
||||
spi_ctrl_new = CTRL_POS_FLANK;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
CTRL_POS_FLANK: begin
|
||||
spi_rx_data_nxt = 1'h1;
|
||||
spi_csk_new = 1'h1;
|
||||
spi_csk_we = 1'h1;
|
||||
spi_clk_ctr_rst = 1'h1;
|
||||
spi_ctrl_new = CTRL_WAIT_POS;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
|
||||
CTRL_WAIT_POS: begin
|
||||
if (spi_clk_ctr_reg == 4'hf) begin
|
||||
spi_ctrl_new = CTRL_NEG_FLANK;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
CTRL_NEG_FLANK: begin
|
||||
spi_csk_new = 1'h0;
|
||||
spi_csk_we = 1'h1;
|
||||
spi_clk_ctr_rst = 1'h1;
|
||||
spi_ctrl_new = CTRL_WAIT_NEG;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
|
||||
CTRL_WAIT_NEG: begin
|
||||
if (spi_clk_ctr_reg == 4'hf) begin
|
||||
spi_ctrl_new = CTRL_NEXT;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
CTRL_NEXT: begin
|
||||
if (spi_bit_ctr_reg == 3'h7) begin
|
||||
spi_ready_new = 1'h1;
|
||||
spi_ready_we = 1'h1;
|
||||
spi_ctrl_new = CTRL_IDLE;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
else begin
|
||||
spi_tx_data_nxt = 1'h1;
|
||||
spi_bit_ctr_inc = 1'h1;
|
||||
spi_ctrl_new = CTRL_POS_FLANK;
|
||||
spi_ctrl_we = 1'h1;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
end
|
||||
endcase // case (spi_ctrl_reg)
|
||||
end
|
||||
|
||||
endmodule // tk1_spi_master
|
||||
|
||||
//======================================================================
|
||||
// EOF tk1_spi_master.v
|
||||
//======================================================================
|
@ -37,6 +37,10 @@ lint-top: $(LINT_SRC)
|
||||
$(LINT) $(LINT_FLAGS) $(LINT_SRC)
|
||||
|
||||
|
||||
lint-spi: $(SPI_SRC)
|
||||
$(LINT) $(LINT_FLAGS) $^
|
||||
|
||||
|
||||
clean:
|
||||
rm -f top.sim
|
||||
|
||||
|
@ -18,6 +18,13 @@ set_io interface_tx 25
|
||||
# set_io interface_rts 28
|
||||
|
||||
|
||||
# SPI master to flash memory.
|
||||
set_io spi_miso 17
|
||||
set_io spi_sck 15
|
||||
set_io spi_ss 16
|
||||
set_io spi_mosi 14
|
||||
|
||||
|
||||
# Touch sense.
|
||||
set_io touch_event 6
|
||||
|
||||
|
@ -141,4 +141,8 @@
|
||||
#define TK1_MMIO_TK1_CPU_MON_CTRL 0xff000180
|
||||
#define TK1_MMIO_TK1_CPU_MON_FIRST 0xff000184
|
||||
#define TK1_MMIO_TK1_CPU_MON_LAST 0xff000188
|
||||
|
||||
#define TK1_MMIO_TK1_SPI_EN 0xff000200
|
||||
#define TK1_MMIO_TK1_SPI_XFER 0xff000204
|
||||
#define TK1_MMIO_TK1_SPI_DATA 0xff000208
|
||||
#endif
|
||||
|
@ -20,6 +20,13 @@ module application_fpga(
|
||||
output wire interface_rx,
|
||||
input wire interface_tx,
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
output wire spi_ss,
|
||||
output wire spi_sck,
|
||||
output wire spi_mosi,
|
||||
input wire spi_miso,
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
input wire touch_event,
|
||||
|
||||
input wire app_gpio1,
|
||||
@ -317,6 +324,13 @@ module application_fpga(
|
||||
.ram_aslr(ram_aslr),
|
||||
.ram_scramble(ram_scramble),
|
||||
|
||||
`ifdef INCLUDE_SPI_MASTER
|
||||
.spi_ss(spi_ss),
|
||||
.spi_sck(spi_sck),
|
||||
.spi_mosi(spi_mosi),
|
||||
.spi_miso(spi_miso),
|
||||
`endif // INCLUDE_SPI_MASTER
|
||||
|
||||
.led_r(led_r),
|
||||
.led_g(led_g),
|
||||
.led_b(led_b),
|
||||
|
Loading…
Reference in New Issue
Block a user