mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
transferred spi changes in ECA-authorized commit
This commit is contained in:
parent
2f6e39defc
commit
1fa4ad90ec
@ -118,6 +118,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b1;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Bus Interface width
|
||||
localparam AHBW = 32'd64;
|
||||
@ -126,6 +129,7 @@ localparam AHBW = 32'd64;
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 0;
|
||||
localparam SPI_LOOPBACK_TEST = 0;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd0;
|
||||
@ -135,6 +139,7 @@ localparam PLIC_NUM_SRC = 32'd53;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd20;
|
||||
|
||||
localparam BPRED_SUPPORTED = 1;
|
||||
|
@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Bus Interface width
|
||||
localparam AHBW = 32'd32;
|
||||
@ -127,6 +130,7 @@ localparam AHBW = 32'd32;
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 0;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -137,6 +141,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 0;
|
||||
|
@ -120,6 +120,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b1;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Bus Interface width
|
||||
localparam AHBW = 32'd32;
|
||||
@ -128,6 +131,7 @@ localparam AHBW = 32'd32;
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -138,6 +142,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 1;
|
||||
|
@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Bus Interface width
|
||||
localparam AHBW = 32'd32;
|
||||
@ -127,6 +130,7 @@ localparam AHBW = 32'd32;
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -137,6 +141,8 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 0;
|
||||
|
@ -118,6 +118,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b1;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Bus Interface width
|
||||
localparam AHBW = 32'd32;
|
||||
@ -126,6 +129,7 @@ localparam AHBW = 32'd32;
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -136,6 +140,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 0;
|
||||
|
@ -124,11 +124,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b1;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -139,6 +143,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 1;
|
||||
|
@ -127,11 +127,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b1;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -142,6 +146,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 1;
|
||||
|
@ -124,11 +124,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||
localparam SDC_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
||||
localparam SPI_SUPPORTED = 1'b0;
|
||||
localparam logic [63:0] SPI_BASE = 64'h10040000;
|
||||
localparam logic [63:0] SPI_RANGE = 64'h00000FFF;
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
localparam GPIO_LOOPBACK_TEST = 1;
|
||||
localparam SPI_LOOPBACK_TEST = 1;
|
||||
|
||||
// Hardware configuration
|
||||
localparam UART_PRESCALE = 32'd1;
|
||||
@ -139,6 +143,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||
localparam PLIC_GPIO_ID = 32'd3;
|
||||
localparam PLIC_UART_ID = 32'd10;
|
||||
localparam PLIC_SPI_ID = 32'd6;
|
||||
localparam PLIC_SDC_ID = 32'd9;
|
||||
|
||||
localparam BPRED_SUPPORTED = 0;
|
||||
|
@ -73,12 +73,17 @@ localparam cvw_t P = '{
|
||||
SDC_SUPPORTED : SDC_SUPPORTED,
|
||||
SDC_BASE : SDC_BASE,
|
||||
SDC_RANGE : SDC_RANGE,
|
||||
SPI_SUPPORTED : SPI_SUPPORTED,
|
||||
SPI_BASE : SPI_BASE,
|
||||
SPI_RANGE : SPI_RANGE,
|
||||
GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST,
|
||||
SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST,
|
||||
UART_PRESCALE : UART_PRESCALE ,
|
||||
PLIC_NUM_SRC : PLIC_NUM_SRC,
|
||||
PLIC_NUM_SRC_LT_32 : PLIC_NUM_SRC_LT_32,
|
||||
PLIC_GPIO_ID : PLIC_GPIO_ID,
|
||||
PLIC_UART_ID : PLIC_UART_ID,
|
||||
PLIC_SPI_ID : PLIC_SPI_ID,
|
||||
PLIC_SDC_ID : PLIC_SDC_ID,
|
||||
BPRED_SUPPORTED : BPRED_SUPPORTED,
|
||||
/* verilator lint_off ENUMVALUE */
|
||||
|
@ -128,11 +128,15 @@ typedef struct packed {
|
||||
logic SDC_SUPPORTED;
|
||||
logic [63:0] SDC_BASE;
|
||||
logic [63:0] SDC_RANGE;
|
||||
logic SPI_SUPPORTED;
|
||||
logic [63:0] SPI_BASE;
|
||||
logic [63:0] SPI_RANGE;
|
||||
|
||||
// Test modes
|
||||
|
||||
// Tie GPIO outputs back to inputs
|
||||
logic GPIO_LOOPBACK_TEST;
|
||||
logic SPI_LOOPBACK_TEST;
|
||||
|
||||
// Hardware configuration
|
||||
int UART_PRESCALE ;
|
||||
@ -142,6 +146,7 @@ typedef struct packed {
|
||||
logic PLIC_NUM_SRC_LT_32;
|
||||
int PLIC_GPIO_ID;
|
||||
int PLIC_UART_ID;
|
||||
int PLIC_SPI_ID;
|
||||
int PLIC_SDC_ID;
|
||||
|
||||
logic BPRED_SUPPORTED;
|
||||
|
@ -32,23 +32,24 @@ module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||
input logic AccessRW, AccessRX, AccessRWX,
|
||||
input logic [1:0] Size,
|
||||
output logic [10:0] SelRegions
|
||||
output logic [11:0] SelRegions
|
||||
);
|
||||
|
||||
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[10]);
|
||||
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
||||
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[8]);
|
||||
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[7]);
|
||||
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[6]);
|
||||
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[5]);
|
||||
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[4]);
|
||||
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[3]);
|
||||
adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[2]);
|
||||
adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[1]);
|
||||
adrdec #(P.PA_BITS) dtimdec(PhysicalAddress, P.DTIM_BASE[P.PA_BITS-1:0], P.DTIM_RANGE[P.PA_BITS-1:0], P.DTIM_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[11]);
|
||||
adrdec #(P.PA_BITS) iromdec(PhysicalAddress, P.IROM_BASE[P.PA_BITS-1:0], P.IROM_RANGE[P.PA_BITS-1:0], P.IROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[10]);
|
||||
adrdec #(P.PA_BITS) ddr4dec(PhysicalAddress, P.EXT_MEM_BASE[P.PA_BITS-1:0], P.EXT_MEM_RANGE[P.PA_BITS-1:0], P.EXT_MEM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[9]);
|
||||
adrdec #(P.PA_BITS) bootromdec(PhysicalAddress, P.BOOTROM_BASE[P.PA_BITS-1:0], P.BOOTROM_RANGE[P.PA_BITS-1:0], P.BOOTROM_SUPPORTED, AccessRX, Size, SUPPORTED_SIZE, SelRegions[8]);
|
||||
adrdec #(P.PA_BITS) uncoreramdec(PhysicalAddress, P.UNCORE_RAM_BASE[P.PA_BITS-1:0], P.UNCORE_RAM_RANGE[P.PA_BITS-1:0], P.UNCORE_RAM_SUPPORTED, AccessRWX, Size, SUPPORTED_SIZE, SelRegions[7]);
|
||||
adrdec #(P.PA_BITS) clintdec(PhysicalAddress, P.CLINT_BASE[P.PA_BITS-1:0], P.CLINT_RANGE[P.PA_BITS-1:0], P.CLINT_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE, SelRegions[6]);
|
||||
adrdec #(P.PA_BITS) gpiodec(PhysicalAddress, P.GPIO_BASE[P.PA_BITS-1:0], P.GPIO_RANGE[P.PA_BITS-1:0], P.GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[5]);
|
||||
adrdec #(P.PA_BITS) uartdec(PhysicalAddress, P.UART_BASE[P.PA_BITS-1:0], P.UART_RANGE[P.PA_BITS-1:0], P.UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[4]);
|
||||
adrdec #(P.PA_BITS) plicdec(PhysicalAddress, P.PLIC_BASE[P.PA_BITS-1:0], P.PLIC_RANGE[P.PA_BITS-1:0], P.PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[3]);
|
||||
adrdec #(P.PA_BITS) sdcdec(PhysicalAddress, P.SDC_BASE[P.PA_BITS-1:0], P.SDC_RANGE[P.PA_BITS-1:0], P.SDC_SUPPORTED, AccessRW, Size, SUPPORTED_SIZE & 4'b1100, SelRegions[2]);
|
||||
adrdec #(P.PA_BITS) spidec(PhysicalAddress, P.SPI_BASE[P.PA_BITS-1:0], P.SPI_RANGE[P.PA_BITS-1:0], P.SPI_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[1]);
|
||||
|
||||
assign SelRegions[0] = ~|(SelRegions[10:1]); // none of the regions are selected
|
||||
assign SelRegions[0] = ~|(SelRegions[11:1]); // none of the regions are selected
|
||||
endmodule
|
||||
|
||||
// verilator lint_on UNOPTFLAT
|
||||
|
@ -44,7 +44,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
logic PMAAccessFault;
|
||||
logic AccessRW, AccessRWX, AccessRX;
|
||||
logic [10:0] SelRegions;
|
||||
logic [11:0] SelRegions;
|
||||
logic AtomicAllowed;
|
||||
logic CacheableRegion, IdempotentRegion;
|
||||
|
||||
@ -57,18 +57,18 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
||||
|
||||
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
|
||||
assign CacheableRegion = SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-cachable
|
||||
assign CacheableRegion = SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-cachable
|
||||
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0;
|
||||
|
||||
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
|
||||
// I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent
|
||||
assign IdempotentRegion = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-idempotent
|
||||
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01);
|
||||
assign IdempotentRegion = SelRegions[11] | SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7];
|
||||
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01); // exclusion-tag: unused-idempotent
|
||||
|
||||
// Atomic operations are only allowed on RAM
|
||||
assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6]; // exclusion-tag: unused-atomic
|
||||
assign AtomicAllowed = SelRegions[11] | SelRegions[9] | SelRegions[7];
|
||||
// Check if tightly integrated memories are selected
|
||||
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
||||
assign SelTIM = SelRegions[11] | SelRegions[10];
|
||||
|
||||
// Detect access faults
|
||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||
|
@ -49,7 +49,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PENABLE,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,SDCIntr,
|
||||
input logic UARTIntr,GPIOIntr, SPIIntr, SDCIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
);
|
||||
|
||||
@ -160,6 +160,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
requests = {P.PLIC_NUM_SRC{1'b0}};
|
||||
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
|
||||
if(P.PLIC_UART_ID != 0) requests[P.PLIC_UART_ID] = UARTIntr;
|
||||
if(P.PLIC_SPI_ID != 0) requests[P.PLIC_SPI_ID] = SPIIntr;
|
||||
if(P.PLIC_SDC_ID !=0) requests[P.PLIC_SDC_ID] = SDCIntr;
|
||||
end
|
||||
|
||||
|
746
src/uncore/spi_apb.sv
Normal file
746
src/uncore/spi_apb.sv
Normal file
@ -0,0 +1,746 @@
|
||||
///////////////////////////////////////////
|
||||
// spi_apb.sv
|
||||
//
|
||||
// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022
|
||||
|
||||
//
|
||||
// Purpose: SPI peripheral
|
||||
// See FU540-C000-v1.0 for specifications
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
||||
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work distributed under the
|
||||
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// either express or implied. See the License for the specific language governing permissions
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan.
|
||||
// Hardware interlocks to ensure transfer finishes before register changes unimplemented
|
||||
//TODO: change tests to reflect swizzled Delay0, Delay1, Format
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [7:0] PADDR,
|
||||
input logic [P.XLEN-1:0] PWDATA,
|
||||
input logic [P.XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic PREADY,
|
||||
output logic [P.XLEN-1:0] PRDATA,
|
||||
output logic [3:0] SPIOut,
|
||||
input logic [3:0] SPIIn,
|
||||
output logic [3:0] SPICS,
|
||||
output logic SPIIntr
|
||||
|
||||
);
|
||||
|
||||
//SPI registers
|
||||
|
||||
logic [11:0] SckDiv;
|
||||
logic [1:0] SckMode;
|
||||
logic [1:0] ChipSelectID;
|
||||
logic [3:0] ChipSelectDef;
|
||||
logic [1:0] ChipSelectMode;
|
||||
logic [15:0] Delay0, Delay1;
|
||||
logic [7:0] Format;
|
||||
logic [8:0] ReceiveData;
|
||||
logic [8:0] ReceiveDataPlaceholder;
|
||||
logic [2:0] TransmitWatermark, ReceiveWatermark;
|
||||
logic [8:0] TransmitData;
|
||||
logic [1:0] InterruptEnable, InterruptPending;
|
||||
|
||||
//bus interface signals
|
||||
logic [7:0] Entry;
|
||||
logic Memwrite;
|
||||
logic [31:0] Din, Dout;
|
||||
logic busy;
|
||||
|
||||
//FIFO FSM signals
|
||||
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
||||
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
||||
logic TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement;
|
||||
logic ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement;
|
||||
|
||||
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
||||
logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
|
||||
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
|
||||
|
||||
logic TransmitFIFOReadEmptyDelay;
|
||||
logic [7:0] ReceiveShiftRegEndian;
|
||||
|
||||
//transmission signals
|
||||
logic sck;
|
||||
logic [12:0] DivCounter;
|
||||
logic SCLKDuty;
|
||||
logic [8:0] Delay0Count;
|
||||
logic [8:0] Delay1Count;
|
||||
logic Delay0Compare;
|
||||
logic Delay1Compare;
|
||||
logic InterCSCompare;
|
||||
logic [8:0] InterCSCount;
|
||||
logic InterXFRCompare;
|
||||
logic [8:0] InterXFRCount;
|
||||
logic [3:0] ChipSelectInternal;
|
||||
logic [4:0] FrameCount;
|
||||
logic [4:0] FrameCompare;
|
||||
|
||||
logic FrameCompareBoolean;
|
||||
logic [4:0] FrameCountShifted;
|
||||
logic [4:0] ReceivePenultimateFrame;
|
||||
logic [4:0] ReceivePenultimateFrameCount;
|
||||
logic ReceivePenultimateFrameBoolean;
|
||||
logic [4:0] FrameCompareProtocol;
|
||||
logic ReceiveShiftFull;
|
||||
logic TransmitShiftEmpty;
|
||||
logic HoldModeDeassert;
|
||||
|
||||
|
||||
//state fsm signals
|
||||
logic Active;
|
||||
logic Active0;
|
||||
logic Inactive;
|
||||
|
||||
//shift reg signals
|
||||
logic TransmitFIFOWriteIncrementDelay;
|
||||
logic sckPhaseSelect;
|
||||
logic [7:0] TransmitShiftReg;
|
||||
logic [7:0] ReceiveShiftReg;
|
||||
logic SampleEdge;
|
||||
logic [7:0] TransmitDataEndian;
|
||||
logic TransmitShiftRegLoad;
|
||||
|
||||
//CS signals
|
||||
logic [3:0] ChipSelectAuto, ChipSelectHold, CSoff;
|
||||
logic ChipSelectHoldSingle;
|
||||
|
||||
logic ReceiveShiftFullDelay;
|
||||
|
||||
|
||||
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||
assign PREADY = 1'b1; // spi never takes >1 cycle to respond (float module)
|
||||
|
||||
// account for subword read/write circuitry
|
||||
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
|
||||
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
|
||||
if (P.XLEN == 64) begin
|
||||
assign Din = Entry[2] ? PWDATA[63:32] : PWDATA[31:0];
|
||||
assign PRDATA = Entry[2] ? {Dout,32'b0} : {32'b0,Dout};
|
||||
end else begin // 32-bit
|
||||
assign Din = PWDATA[31:0];
|
||||
assign PRDATA = Dout;
|
||||
end
|
||||
|
||||
// register access
|
||||
always_ff@(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
SckDiv <= #1 12'd3;
|
||||
SckMode <= #1 2'b0;
|
||||
ChipSelectID <= #1 2'b0;
|
||||
ChipSelectDef <= #1 4'b1111;
|
||||
ChipSelectMode <= #1 0;
|
||||
Delay0 <= #1 {8'b1,8'b1};
|
||||
Delay1 <= #1 {8'b0,8'b1};
|
||||
Format <= #1 {8'b10000000};
|
||||
TransmitData <= #1 9'b0;
|
||||
//ReceiveData <= #1 9'b100000000;
|
||||
TransmitWatermark <= #1 3'b0;
|
||||
ReceiveWatermark <= #1 3'b0;
|
||||
InterruptEnable <= #1 2'b0;
|
||||
InterruptPending <= #1 2'b0;
|
||||
end else begin //writes
|
||||
//According to FU540 spec: Once interrupt is pending, it will remain set until number
|
||||
//of entries in tx/rx fifo is strictly more/less than tx/rxmark
|
||||
|
||||
//From spec. "Hardware interlocks ensure that the current transfer completes before mode transitions and control register updates take effect"
|
||||
// Interpreting 'current transfer' as one frame
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
if (Memwrite)
|
||||
case(Entry) //flop to sample inputs
|
||||
8'h00: SckDiv <= Din[11:0];
|
||||
8'h04: SckMode <= Din[1:0];
|
||||
8'h10: ChipSelectID <= Din[1:0];
|
||||
8'h14: ChipSelectDef <= Din[3:0];
|
||||
8'h18: ChipSelectMode <= Din[1:0];
|
||||
8'h28: Delay0 <= {Din[23:16], Din[7:0]};
|
||||
8'h2C: Delay1 <= {Din[23:16], Din[7:0]};
|
||||
8'h40: Format <= {Din[19:16], Din[3:0]};
|
||||
8'h48: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0];
|
||||
8'h50: TransmitWatermark <= Din[2:0];
|
||||
8'h54: ReceiveWatermark <= Din[2:0];
|
||||
8'h70: InterruptEnable <= Din[1:0];
|
||||
endcase
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
//interrupt clearance
|
||||
InterruptPending[0] <= TransmitReadMark;
|
||||
InterruptPending[1] <= RecieveWriteMark;
|
||||
case(Entry) // flop to sample inputs
|
||||
8'h00: Dout[11:0] <= #1 SckDiv;
|
||||
8'h04: Dout[1:0] <= #1 SckMode;
|
||||
8'h10: Dout[1:0] <= #1 ChipSelectID;
|
||||
8'h14: Dout[3:0] <= #1 ChipSelectDef;
|
||||
8'h18: Dout[1:0] <= #1 ChipSelectMode;
|
||||
8'h28: begin
|
||||
Dout[23:16] <= #1 Delay0[15:8]; // swizzle
|
||||
Dout[7:0] <= #1 Delay0[7:0];
|
||||
end
|
||||
8'h2C: begin
|
||||
Dout[23:16] <= #1 Delay1[15:8]; // swizzle
|
||||
Dout[7:0] <= #1 Delay1[7:0];
|
||||
end
|
||||
8'h40: begin
|
||||
Dout[19:16] <= #1 Format[7:4]; // swizzle
|
||||
Dout[3:0] <= #1 Delay0[3:0];
|
||||
end
|
||||
8'h48: Dout[8:0] <= #1 {TransmitFIFOWriteFull, 8'b0};
|
||||
8'h4C: Dout[8:0] <= #1 {ReceiveFIFOReadEmpty, ReceiveData[7:0]};
|
||||
8'h50: Dout[2:0] <= #1 TransmitWatermark;
|
||||
8'h54: Dout[2:0] <= #1 ReceiveWatermark;
|
||||
8'h70: Dout[1:0] <= #1 InterruptEnable;
|
||||
8'h74: Dout[1:0] <= #1 InterruptPending;
|
||||
default: Dout <= #1 32'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//SCK_CONTROL
|
||||
//multiplies frame count by 2 or 4 if in dual or quad mode
|
||||
|
||||
always_comb
|
||||
case(Format[1:0])
|
||||
2'b00: FrameCountShifted = FrameCount;
|
||||
2'b01: FrameCountShifted = {FrameCount[3:0], 1'b0};
|
||||
2'b10: FrameCountShifted = {FrameCount[2:0], 2'b0};
|
||||
default: FrameCountShifted = FrameCount;
|
||||
endcase
|
||||
|
||||
//Calculates penultimate frame
|
||||
//Frame compare doubles number of frames in dual or qyad mode to account for half-duplex communication
|
||||
//FrameCompareProtocol further adjusts comparison according to dual or quad mode
|
||||
|
||||
always_comb
|
||||
case(Format[1:0])
|
||||
2'b00: begin
|
||||
ReceivePenultimateFrame = 5'b00001;
|
||||
FrameCompareProtocol = FrameCompare;
|
||||
end
|
||||
2'b01: begin
|
||||
ReceivePenultimateFrame = 5'b00010;
|
||||
//add 1 to count if # of bits is odd so doubled # will be correct
|
||||
// for ex. 5 bits needs 3 frames, 5*2 = 10 which will be reached in 5 frames not 3*2.
|
||||
FrameCompareProtocol = Format[4] ? FrameCompare + 5'b1 : FrameCompare;
|
||||
end
|
||||
2'b10: begin
|
||||
ReceivePenultimateFrame = 5'b00100;
|
||||
//if frame len =< 4, need 2 frames (one to send 1-4 bits, one to recieve)
|
||||
//else, 4 < frame len =<8 8, which by same logic needs 4 frames
|
||||
if (Format[7:4] > 4'b0100) FrameCompareProtocol = 5'b10000;
|
||||
else FrameCompareProtocol = 5'b01000;
|
||||
end
|
||||
default: begin
|
||||
ReceivePenultimateFrame = 5'b00001;
|
||||
FrameCompareProtocol = FrameCompare;
|
||||
end
|
||||
|
||||
endcase
|
||||
|
||||
//Signals that track frame count comparisons
|
||||
|
||||
assign FrameCompareBoolean = (FrameCountShifted < FrameCompareProtocol);
|
||||
assign ReceivePenultimateFrameCount = FrameCountShifted + ReceivePenultimateFrame;
|
||||
assign ReceivePenultimateFrameBoolean = (ReceivePenultimateFrameCount >= FrameCompareProtocol);
|
||||
|
||||
// Computing delays
|
||||
// When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs
|
||||
|
||||
|
||||
assign Delay0Compare = SckMode[0] ? (Delay0Count >= ({Delay0[7:0], 1'b0})) : (Delay0Count >= ({Delay0[7:0], 1'b0} + 9'b1));
|
||||
assign Delay1Compare = SckMode[0] ? (Delay1Count >= (({Delay0[15:8], 1'b0}) + 9'b1)) : (Delay1Count >= ({Delay0[15:8], 1'b0}));
|
||||
assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
|
||||
assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0}));
|
||||
|
||||
|
||||
// double number of frames in dual or quad mode because we must wait for peripheral to send back
|
||||
assign FrameCompare = (Format[0] | Format[1]) ? ({Format[7:4], 1'b0}) : {1'b0,Format[7:4]};
|
||||
|
||||
|
||||
|
||||
// Producing SCLK
|
||||
// SCLK = PCLK/(2*(sclk_div + 1))
|
||||
// SCLKDuty is high every half-period of SCLK
|
||||
|
||||
assign SCLKDuty = (DivCounter >= {1'b0,SckDiv});
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) DivCounter <= #1 0;
|
||||
else if (SCLKDuty) DivCounter <= 0;
|
||||
else DivCounter <= DivCounter + 13'b1;
|
||||
|
||||
//Main FSM which controls SPI transmission
|
||||
|
||||
typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype;
|
||||
statetype state;
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin state <= CS_INACTIVE;
|
||||
FrameCount <= 5'b0;
|
||||
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
end else if (SCLKDuty) begin
|
||||
case (state)
|
||||
CS_INACTIVE: begin
|
||||
Delay0Count <= 9'b1;
|
||||
Delay1Count <= 9'b10;
|
||||
FrameCount <= 5'b0;
|
||||
InterCSCount <= 9'b10;
|
||||
InterXFRCount <= 9'b1;
|
||||
if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
|
||||
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
|
||||
end
|
||||
DELAY_0: begin
|
||||
Delay0Count <= Delay0Count + 9'b1;
|
||||
if (Delay0Compare) state <= ACTIVE_0;
|
||||
end
|
||||
ACTIVE_0: begin
|
||||
FrameCount <= FrameCount + 5'b1;
|
||||
state <= ACTIVE_1;
|
||||
end
|
||||
ACTIVE_1: begin
|
||||
InterXFRCount <= 9'b1;
|
||||
if (FrameCompareBoolean) state <= ACTIVE_0;
|
||||
else if (HoldModeDeassert) state <= CS_INACTIVE;
|
||||
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
|
||||
state <= ACTIVE_0;
|
||||
Delay0Count <= 9'b1;
|
||||
Delay1Count <= 9'b10;
|
||||
FrameCount <= 5'b0;
|
||||
InterCSCount <= 9'b10;
|
||||
end
|
||||
else if (ChipSelectMode[1:0] == 2'b10) state <= INTER_XFR;
|
||||
else if (~|(Delay0[15:8]) & (~SckMode[0])) state <= INTER_CS;
|
||||
else state <= DELAY_1;
|
||||
end
|
||||
DELAY_1: begin
|
||||
Delay1Count <= Delay1Count + 9'b1;
|
||||
if (Delay1Compare) state <= INTER_CS;
|
||||
end
|
||||
INTER_CS: begin
|
||||
InterCSCount <= InterCSCount + 9'b1;
|
||||
if (InterCSCompare ) state <= CS_INACTIVE;
|
||||
end
|
||||
INTER_XFR: begin
|
||||
Delay0Count <= 9'b1;
|
||||
Delay1Count <= 9'b10;
|
||||
FrameCount <= 5'b0;
|
||||
InterCSCount <= 9'b10;
|
||||
InterXFRCount <= InterXFRCount + 9'b1;
|
||||
if (HoldModeDeassert) state <= CS_INACTIVE;
|
||||
else if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
|
||||
else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
|
||||
|
||||
assign ChipSelectInternal = SckMode[0] ? ((state == CS_INACTIVE | state == INTER_CS | (state == DELAY_1 & ~|(Delay0[15:8]))) ? ChipSelectDef : ~ChipSelectDef) : ((state == CS_INACTIVE | state == INTER_CS | (state == ACTIVE_1 & ~|(Delay0[15:8]) & ReceiveShiftFull)) ? ChipSelectDef : ~ChipSelectDef);
|
||||
assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
|
||||
assign busy = (state == DELAY_0 | state == ACTIVE_0 | ((state == ACTIVE_1) & ~((|(Delay1[15:8]) & (ChipSelectMode[1:0]) == 2'b10) & ((FrameCount << Format[1:0]) >= FrameCompare))) | state == DELAY_1);
|
||||
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
|
||||
|
||||
assign Active0 = (state == ACTIVE_0);
|
||||
assign Inactive = (state == CS_INACTIVE);
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) HoldModeDeassert <= 0;
|
||||
else if (Inactive) HoldModeDeassert <= 0;
|
||||
/* verilator lint_off WIDTH */
|
||||
else if (((ChipSelectMode[1:0] == 2'b10) & (Entry == (8'h18 | 8'h10) | ((Entry == 8'h14) & ((PWDATA[ChipSelectID]) != ChipSelectDef[ChipSelectID])))) & Memwrite) HoldModeDeassert <= 1;
|
||||
/* verilator lint_on WIDTH */
|
||||
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull);
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
|
||||
else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
|
||||
assign TransmitFIFOReadIncrement = TransmitShiftEmpty;
|
||||
|
||||
assign ReceiveFIFOWriteIncrement = ReceiveShiftFullDelay;
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
|
||||
else if (~ReceiveFIFOReadIncrement) ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL);
|
||||
else ReceiveFIFOReadIncrement <= 0;
|
||||
//replace literal 9th bit of ReceiveData register with concatenation of 1 bit empty signal and 8 bits of data
|
||||
//so that all resets can be handled at the same time
|
||||
|
||||
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
|
||||
assign TransmitDataEndian = Format[2] ? {TransmitData[0], TransmitData[1], TransmitData[2], TransmitData[3], TransmitData[4], TransmitData[5], TransmitData[6], TransmitData[7]} : TransmitData[7:0];
|
||||
|
||||
TransmitFIFO #(3,8) txFIFO(PCLK, SCLKDuty, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitFIFOReadIncrement, TransmitDataEndian,TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
|
||||
ReceiveFIFO #(3,8) rxFIFO(SCLKDuty, PCLK, PRESETn, ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
|
||||
|
||||
TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
|
||||
ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKDuty, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
|
||||
else if (SCLKDuty) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
|
||||
logic SCLKDutyDelay;
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) SCLKDutyDelay <= 0;
|
||||
else SCLKDutyDelay <= SCLKDuty;
|
||||
|
||||
always_comb
|
||||
case(SckMode[1:0])
|
||||
2'b00: sckPhaseSelect = ~sck & SCLKDuty;
|
||||
2'b01: sckPhaseSelect = (sck & |(FrameCount) & SCLKDuty);
|
||||
2'b10: sckPhaseSelect = sck & SCLKDuty;
|
||||
2'b11: sckPhaseSelect = (~sck & |(FrameCount) & SCLKDuty);
|
||||
default: sckPhaseSelect = sck & SCLKDuty;
|
||||
endcase
|
||||
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) ReceiveShiftFullDelay <= 0;
|
||||
else if (SCLKDuty) ReceiveShiftFullDelay <= ReceiveShiftFull;
|
||||
|
||||
assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if(~PRESETn) begin
|
||||
TransmitShiftReg <= 8'b0;
|
||||
end
|
||||
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitFIFOReadData;
|
||||
else if (sckPhaseSelect) begin
|
||||
//if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & TransmitShiftEmpty) TransmitShiftReg <= TransmitFIFOReadData;
|
||||
if (Active) begin
|
||||
case (Format[1:0])
|
||||
2'b00: TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
|
||||
2'b01: TransmitShiftReg <= {TransmitShiftReg[5:0], 2'b0};
|
||||
2'b10: TransmitShiftReg <= {TransmitShiftReg[3:0], 4'b0};
|
||||
default: TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
|
||||
endcase
|
||||
end
|
||||
end
|
||||
always_comb
|
||||
if (Active | Delay0Compare | ~TransmitShiftEmpty) begin
|
||||
case(Format[1:0])
|
||||
2'b00: SPIOut = {3'b0,TransmitShiftReg[7]};
|
||||
2'b01: SPIOut = {2'b0,TransmitShiftReg[6], TransmitShiftReg[7]};
|
||||
// assuming SPIOut[0] is first bit transmitted etc
|
||||
2'b10: SPIOut = {TransmitShiftReg[3], TransmitShiftReg[2], TransmitShiftReg[1], TransmitShiftReg[0]};
|
||||
default: SPIOut = {3'b0, TransmitShiftReg[7]};
|
||||
endcase
|
||||
end else SPIOut = 4'b0;
|
||||
logic [3:0] shiftin;
|
||||
assign shiftin = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
||||
else if (SampleEdge & SCLKDuty) begin
|
||||
if (~Active) ReceiveShiftReg <= 8'b0;
|
||||
else if (~Format[3]) begin
|
||||
case(Format[1:0])
|
||||
2'b00: ReceiveShiftReg <= { ReceiveShiftReg[6:0], shiftin[0]};
|
||||
2'b01: ReceiveShiftReg <= { ReceiveShiftReg[5:0], shiftin[0],shiftin[1]};
|
||||
2'b10: ReceiveShiftReg <= { ReceiveShiftReg[3:0], shiftin[0], shiftin[1], shiftin[2], shiftin[3]};
|
||||
default: ReceiveShiftReg <= { ReceiveShiftReg[6:0], shiftin[0]};
|
||||
endcase
|
||||
end
|
||||
end
|
||||
logic [7:0] ReceiveShiftRegInvert;
|
||||
assign ReceiveShiftRegInvert = (Format[2]) ? {ReceiveShiftReg[0], ReceiveShiftReg[1], ReceiveShiftReg[2], ReceiveShiftReg[3], ReceiveShiftReg[4], ReceiveShiftReg[5], ReceiveShiftReg[6], ReceiveShiftReg[7]} : ReceiveShiftReg[7:0];
|
||||
|
||||
always_comb
|
||||
if (Format[2]) begin
|
||||
case(Format[7:4])
|
||||
4'b0001: ReceiveShiftRegEndian = {7'b0, ReceiveShiftRegInvert[7]};
|
||||
4'b0010: ReceiveShiftRegEndian = {6'b0, ReceiveShiftRegInvert[7:6]};
|
||||
4'b0011: ReceiveShiftRegEndian = {5'b0, ReceiveShiftRegInvert[7:5]};
|
||||
4'b0100: ReceiveShiftRegEndian = {4'b0, ReceiveShiftRegInvert[7:4]};
|
||||
4'b0101: ReceiveShiftRegEndian = {3'b0, ReceiveShiftRegInvert[7:3]};
|
||||
4'b0110: ReceiveShiftRegEndian = {2'b0, ReceiveShiftRegInvert[7:2]};
|
||||
4'b0111: ReceiveShiftRegEndian = {1'b0, ReceiveShiftRegInvert[7:1]};
|
||||
4'b1000: ReceiveShiftRegEndian = ReceiveShiftRegInvert;
|
||||
default: ReceiveShiftRegEndian = ReceiveShiftRegInvert;
|
||||
endcase
|
||||
end else begin
|
||||
case(Format[7:4])
|
||||
4'b0001: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[0], 7'b0};
|
||||
4'b0010: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[1:0], 6'b0};
|
||||
4'b0011: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[2:0], 5'b0};
|
||||
4'b0100: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[3:0], 4'b0};
|
||||
4'b0101: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[4:0], 3'b0};
|
||||
4'b0110: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[5:0], 2'b0};
|
||||
4'b0111: ReceiveShiftRegEndian = {ReceiveShiftRegInvert[6:0], 1'b0};
|
||||
4'b1000: ReceiveShiftRegEndian = ReceiveShiftRegInvert;
|
||||
default: ReceiveShiftRegEndian = ReceiveShiftRegInvert;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign SPIIntr = |(InterruptPending & InterruptEnable);
|
||||
|
||||
always_comb
|
||||
case(ChipSelectID[1:0])
|
||||
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
|
||||
|
||||
2'b01: ChipSelectAuto = {ChipSelectDef[3],ChipSelectDef[2], ChipSelectInternal[1], ChipSelectDef[0]};
|
||||
|
||||
2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[1], ChipSelectDef[0]};
|
||||
|
||||
2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]};
|
||||
endcase
|
||||
|
||||
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
|
||||
|
||||
|
||||
endmodule
|
||||
/*
|
||||
module synchFIFO #(parameter M =3 , N= 8(
|
||||
input logic PCLK, wen, ren, PRESETn,
|
||||
input logic winc,rinc,
|
||||
input logic [N-1:0] wdata,
|
||||
input logic [M-1:0] wwatermarklevel, rwatermarklevel,
|
||||
output logic [N-1:0] rdata,
|
||||
output logic wfull, rempty,
|
||||
output logic wwatermark, rwatermark);
|
||||
|
||||
)
|
||||
*/
|
||||
module TransmitFIFO #(parameter M = 3, N = 8)(
|
||||
input logic wclk, rclk, PRESETn,
|
||||
input logic winc,rinc,
|
||||
input logic [N-1:0] wdata,
|
||||
input logic [M-1:0] wwatermarklevel, rwatermarklevel,
|
||||
output logic [N-1:0] rdata,
|
||||
output logic wfull, rempty,
|
||||
output logic wwatermark, rwatermark);
|
||||
|
||||
logic [N-1:0] mem[2**M];
|
||||
logic [M:0] wq1_rptr, wq2_rptr, rptr;
|
||||
logic [M:0] rq1_wptr, rq2_wptr, wptr;
|
||||
logic [M:0] rbin, rgraynext, rbinnext;
|
||||
logic [M:0] wbin, wgraynext, wbinnext;
|
||||
logic rempty_val;
|
||||
logic wfull_val;
|
||||
logic [M:0] wq2_rptr_bin, rq2_wptr_bin;
|
||||
logic [M-1:0] raddr;
|
||||
logic [M-1:0] waddr;
|
||||
|
||||
assign rdata = mem[raddr];
|
||||
always_ff @(posedge wclk)
|
||||
if(winc & ~wfull) mem[waddr] <= wdata;
|
||||
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
wq2_rptr <= 0;
|
||||
wq1_rptr <= 0;
|
||||
end
|
||||
else begin
|
||||
wq2_rptr <= wq1_rptr;
|
||||
wq1_rptr <= rptr;
|
||||
end
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
rq2_wptr <= 0;
|
||||
rq1_wptr <= 0;
|
||||
end
|
||||
else if (rclk) begin
|
||||
|
||||
rq2_wptr <= rq1_wptr;
|
||||
rq1_wptr <= wptr;
|
||||
end
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if(~PRESETn) begin
|
||||
rbin <= 0;
|
||||
rptr <= 0;
|
||||
end
|
||||
else if (rclk) begin
|
||||
rbin <= rbinnext;
|
||||
rptr <= rgraynext;
|
||||
end
|
||||
assign rq2_wptr_bin = {rq2_wptr[3], (rq2_wptr[3]^rq2_wptr[2]),(rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]), (rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]^rq2_wptr[0]) };
|
||||
assign rwatermark = ((rbin[M-1:0] - rq2_wptr_bin[M-1:0]) < rwatermarklevel);
|
||||
assign raddr = rbin[M-1:0];
|
||||
assign rbinnext = rbin + {3'b0, (rinc & ~rempty)};
|
||||
assign rgraynext = (rbinnext >> 1) ^ rbinnext;
|
||||
assign rempty_val = (rgraynext == rq2_wptr);
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if (~PRESETn) rempty <= 1'b1;
|
||||
else if (rclk) rempty <= rempty_val;
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
wbin <= 0;
|
||||
wptr <= 0;
|
||||
end else begin
|
||||
wbin <= wbinnext;
|
||||
wptr <= wgraynext;
|
||||
end
|
||||
assign waddr = wbin[M-1:0];
|
||||
assign wq2_rptr_bin = {wq2_rptr[3], (wq2_rptr[3]^wq2_rptr[2]),(wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]), (wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]^wq2_rptr[0]) };
|
||||
assign wwatermark = ((wbin[M-1:0] - wq2_rptr_bin[M-1:0]) > wwatermarklevel);
|
||||
assign wbinnext = wbin + {3'b0, (winc & ~wfull)};
|
||||
assign wgraynext = (wbinnext >> 1) ^ wbinnext;
|
||||
|
||||
assign wfull_val = (wgraynext == {(~wq2_rptr[M:M-1]),wq2_rptr[M-2:0]});
|
||||
|
||||
always_ff @(posedge wclk, negedge PRESETn)
|
||||
if (~PRESETn) wfull <= 1'b0;
|
||||
else wfull <= wfull_val;
|
||||
|
||||
endmodule
|
||||
|
||||
module ReceiveFIFO #(parameter M = 3, N = 8)(
|
||||
input logic wclk, rclk, PRESETn,
|
||||
input logic winc,rinc,
|
||||
input logic [N-1:0] wdata,
|
||||
input logic [M-1:0] wwatermarklevel, rwatermarklevel,
|
||||
output logic [N-1:0] rdata,
|
||||
output logic wfull, rempty,
|
||||
output logic wwatermark, rwatermark);
|
||||
|
||||
logic [N-1:0] mem[2**M];
|
||||
logic [M:0] wq1_rptr, wq2_rptr, rptr;
|
||||
logic [M:0] rq1_wptr, rq2_wptr, wptr;
|
||||
logic [M:0] rbin, rgraynext, rbinnext;
|
||||
logic [M:0] wbin, wgraynext, wbinnext;
|
||||
logic rempty_val;
|
||||
logic wfull_val;
|
||||
logic [M:0] wq2_rptr_bin, rq2_wptr_bin;
|
||||
logic [M-1:0] raddr;
|
||||
logic [M-1:0] waddr;
|
||||
|
||||
assign rdata = mem[raddr];
|
||||
always_ff @(posedge rclk)
|
||||
if(winc & ~wfull & wclk) mem[waddr] <= wdata;
|
||||
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
wq2_rptr <= 0;
|
||||
wq1_rptr <= 0;
|
||||
end
|
||||
else if (wclk) begin
|
||||
wq2_rptr <= wq1_rptr;
|
||||
wq1_rptr <= rptr;
|
||||
end
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
rq2_wptr <= 0;
|
||||
rq1_wptr <= 0;
|
||||
end
|
||||
else begin
|
||||
rq2_wptr <= rq1_wptr;
|
||||
rq1_wptr <= wptr;
|
||||
end
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if(~PRESETn) begin
|
||||
rbin <= 0;
|
||||
rptr <= 0;
|
||||
end
|
||||
else begin
|
||||
rbin <= rbinnext;
|
||||
rptr <= rgraynext;
|
||||
end
|
||||
assign rq2_wptr_bin = {rq2_wptr[3], (rq2_wptr[3]^rq2_wptr[2]),(rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]), (rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]^rq2_wptr[0]) };
|
||||
assign rwatermark = ((rbin[M-1:0] - rq2_wptr_bin[M-1:0]) < rwatermarklevel);
|
||||
assign raddr = rbin[M-1:0];
|
||||
assign rbinnext = rbin + {3'b0, (rinc & ~rempty)};
|
||||
assign rgraynext = (rbinnext >> 1) ^ rbinnext;
|
||||
assign rempty_val = (rgraynext == rq2_wptr);
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if (~PRESETn) rempty <= 1'b1;
|
||||
else rempty <= rempty_val;
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
wbin <= 0;
|
||||
wptr <= 0;
|
||||
end else if (wclk) begin
|
||||
wbin <= wbinnext;
|
||||
wptr <= wgraynext;
|
||||
end
|
||||
assign waddr = wbin[M-1:0];
|
||||
assign wq2_rptr_bin = {wq2_rptr[3], (wq2_rptr[3]^wq2_rptr[2]),(wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]), (wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]^wq2_rptr[0]) };
|
||||
assign wwatermark = ((wbin[M-1:0] - wq2_rptr_bin[M-1:0]) > wwatermarklevel);
|
||||
assign wbinnext = wbin + {3'b0, (winc & ~wfull)};
|
||||
assign wgraynext = (wbinnext >> 1) ^ wbinnext;
|
||||
|
||||
assign wfull_val = (wgraynext == {(~wq2_rptr[M:M-1]),wq2_rptr[M-2:0]});
|
||||
|
||||
always_ff @(posedge rclk, negedge PRESETn)
|
||||
if (~PRESETn) wfull <= 1'b0;
|
||||
else if (wclk) wfull <= wfull_val;
|
||||
|
||||
endmodule
|
||||
|
||||
module TransmitShiftFSM(
|
||||
input logic PCLK, PRESETn,
|
||||
input logic TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0,
|
||||
output logic TransmitShiftEmpty);
|
||||
|
||||
typedef enum logic [1:0] {TransmitShiftEmptyState, TransmitShiftHoldState, TransmitShiftNotEmptyState} statetype;
|
||||
statetype TransmitState, TransmitNextState;
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) TransmitState <= TransmitShiftEmptyState;
|
||||
else TransmitState <= TransmitNextState;
|
||||
|
||||
always_comb
|
||||
case(TransmitState)
|
||||
TransmitShiftEmptyState: begin
|
||||
if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrameBoolean & Active0))) TransmitNextState = TransmitShiftEmptyState;
|
||||
else if (~TransmitFIFOReadEmpty) TransmitNextState = TransmitShiftNotEmptyState;
|
||||
end
|
||||
TransmitShiftNotEmptyState: begin
|
||||
if (ReceivePenultimateFrameBoolean & Active0) TransmitNextState = TransmitShiftEmptyState;
|
||||
else TransmitNextState = TransmitShiftNotEmptyState;
|
||||
end
|
||||
endcase
|
||||
assign TransmitShiftEmpty = (TransmitNextState == TransmitShiftEmptyState);
|
||||
endmodule
|
||||
|
||||
module ReceiveShiftFSM(
|
||||
input logic PCLK, PRESETn, SCLKDuty,
|
||||
input logic ReceivePenultimateFrameBoolean, SampleEdge, SckMode,
|
||||
output logic ReceiveShiftFull
|
||||
);
|
||||
typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} statetype;
|
||||
statetype ReceiveState, ReceiveNextState;
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState;
|
||||
else if (SCLKDuty) begin
|
||||
case (ReceiveState)
|
||||
ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
|
||||
ReceiveShiftNotFullState: if (ReceivePenultimateFrameBoolean & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;
|
||||
else ReceiveState <= ReceiveShiftNotFullState;
|
||||
ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign ReceiveShiftFull = SckMode ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState);
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -54,28 +54,31 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||
input logic UARTSin, // UART serial input
|
||||
output logic UARTSout, // UART serial output
|
||||
input logic SDCIntr
|
||||
input logic SDCIntr,
|
||||
input logic [3:0] SPIIn,
|
||||
output logic [3:0] SPIOut,
|
||||
output logic [3:0] SPICS
|
||||
);
|
||||
|
||||
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
||||
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD;
|
||||
logic [11:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC, HSELSPI;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [P.XLEN-1:0] HREADBootRom;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic UARTIntr,GPIOIntr, SPIIntr;
|
||||
logic SDCIntM;
|
||||
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [4:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [P.XLEN-1:0] PWDATA;
|
||||
logic [P.XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][P.XLEN-1:0] PRDATA;
|
||||
logic [4:0][P.XLEN-1:0] PRDATA;
|
||||
logic [P.XLEN-1:0] HREADBRIDGE;
|
||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||
|
||||
@ -88,14 +91,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
|
||||
|
||||
// unswizzle HSEL signals
|
||||
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELEXTSDC} = HSELRegions[10:1];
|
||||
assign {HSELDTIM, HSELIROM, HSELEXT, HSELBootRom, HSELRam, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELSDC, HSELSPI} = HSELRegions[11:1];
|
||||
|
||||
// AHB -> APB bridge
|
||||
ahbapbbridge #(P, 4) ahbapbbridge (
|
||||
.HCLK, .HRESETn, .HSEL({HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
||||
ahbapbbridge #(P, 5) ahbapbbridge (
|
||||
.HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
||||
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
|
||||
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
|
||||
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART; // if any of the bridge signals are selected
|
||||
assign HSELBRIDGE = HSELGPIO | HSELCLINT | HSELPLIC | HSELUART | HSELSPI; // if any of the bridge signals are selected
|
||||
|
||||
// on-chip RAM
|
||||
if (P.UNCORE_RAM_SUPPORTED) begin : ram
|
||||
@ -121,7 +124,7 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
|
||||
if (P.PLIC_SUPPORTED == 1) begin : plic
|
||||
plic_apb #(P) plic(.PCLK, .PRESETn, .PSEL(PSEL[2]), .PADDR(PADDR[27:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[2]), .PREADY(PREADY[2]), .UARTIntr, .GPIOIntr, .SDCIntr, .MExtInt, .SExtInt);
|
||||
.PRDATA(PRDATA[2]), .PREADY(PREADY[2]), .UARTIntr, .GPIOIntr, .SDCIntr, .SPIIntr, .MExtInt, .SExtInt);
|
||||
end else begin : plic
|
||||
assign MExtInt = 0;
|
||||
assign SExtInt = 0;
|
||||
@ -145,6 +148,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
end else begin : uart
|
||||
assign UARTSout = 0; assign UARTIntr = 0;
|
||||
end
|
||||
if (P.SPI_SUPPORTED == 1) begin : spi
|
||||
spi_apb #(P) spi (
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[4]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PREADY(PREADY[4]), .PRDATA(PRDATA[4]),
|
||||
.SPIOut, .SPIIn, .SPICS, .SPIIntr);
|
||||
end else begin : spi
|
||||
assign SPIOut = 0; assign SPICS = 0; assign SPIIntr = 0;
|
||||
end
|
||||
|
||||
// AHB Read Multiplexer
|
||||
assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) |
|
||||
@ -168,6 +179,8 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||
// takes more than 1 cycle to repsond it needs to hold on to the old select until the
|
||||
// device is ready. Hense this register must be selectively enabled by HREADY.
|
||||
// However on reset None must be seleted.
|
||||
flopenl #(11) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 11'b1, {HSELDTIMD, HSELIROMD, HSELEXTD, HSELBootRomD, HSELRamD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELEXTSDCD, HSELNoneD});
|
||||
flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1,
|
||||
{HSELDTIMD, HSELIROMD, HSELEXTD, HSELBootRomD, HSELRamD,
|
||||
HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELEXTSDCD, HSELSPID, HSELNoneD});
|
||||
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
|
||||
endmodule
|
||||
|
@ -54,7 +54,10 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||
input logic UARTSin, // UART serial data input
|
||||
output logic UARTSout, // UART serial data output
|
||||
input logic SDCIntr
|
||||
input logic SDCIntr,
|
||||
input logic [3:0] SPIIn, // SPI pins in
|
||||
output logic [3:0] SPIOut, // SPI pins out
|
||||
output logic [3:0] SPICS // SPI chip select pins
|
||||
);
|
||||
|
||||
// Uncore signals
|
||||
@ -80,7 +83,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC,
|
||||
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
|
||||
.UARTSout, .MTIME_CLINT, .SDCIntr);
|
||||
.UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -64,7 +64,7 @@ module testbench;
|
||||
|
||||
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||
logic UARTSin, UARTSout;
|
||||
|
||||
logic [3:0] SPIIn, SPIOut, SPICS;
|
||||
logic SDCIntr;
|
||||
|
||||
logic HREADY;
|
||||
@ -367,6 +367,7 @@ module testbench;
|
||||
// instantiate device to be tested
|
||||
assign GPIOIN = 0;
|
||||
assign UARTSin = 1;
|
||||
assign SPIIn = 0;
|
||||
|
||||
if(P.EXT_MEM_SUPPORTED) begin
|
||||
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
|
||||
@ -397,7 +398,7 @@ module testbench;
|
||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||
.UARTSin, .UARTSout, .SDCIntr);
|
||||
.UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
|
||||
|
||||
// generate clock to sequence tests
|
||||
always begin
|
||||
|
@ -1974,7 +1974,8 @@ string arch64zbs[] = '{
|
||||
"rv64i_m/privilege/src/WALLY-gpio-01.S",
|
||||
"rv64i_m/privilege/src/WALLY-plic-01.S",
|
||||
"rv64i_m/privilege/src/WALLY-plic-s-01.S",
|
||||
"rv64i_m/privilege/src/WALLY-uart-01.S"
|
||||
"rv64i_m/privilege/src/WALLY-uart-01.S",
|
||||
"rv64i_m/privilege/src/WALLY-spi-01.S"
|
||||
};
|
||||
|
||||
string wally32e[] = '{
|
||||
@ -2060,7 +2061,8 @@ string arch64zbs[] = '{
|
||||
"rv32i_m/privilege/src/WALLY-clint-01.S",
|
||||
"rv32i_m/privilege/src/WALLY-uart-01.S",
|
||||
"rv32i_m/privilege/src/WALLY-plic-01.S",
|
||||
"rv32i_m/privilege/src/WALLY-plic-s-01.S"
|
||||
"rv32i_m/privilege/src/WALLY-plic-s-01.S",
|
||||
"rv32i_m/privilege/src/WALLY-spi-01.S"
|
||||
|
||||
};
|
||||
|
||||
|
@ -57,6 +57,7 @@ target_tests_nosim = \
|
||||
WALLY-clint-01 \
|
||||
WALLY-plic-01 \
|
||||
WALLY-uart-01 \
|
||||
WALLY-spi-01 \
|
||||
WALLY-cbom-01 \
|
||||
WALLY-cboz-01 \
|
||||
|
||||
|
@ -0,0 +1,193 @@
|
||||
00000003 # reset tests sck_div
|
||||
|
||||
00000000 # sck_mode
|
||||
|
||||
00000000 # cs_id
|
||||
|
||||
0000000F # cs_def
|
||||
|
||||
00000000 # cs_mode
|
||||
|
||||
00000101 # delay 0
|
||||
|
||||
00000001 # delay 1
|
||||
|
||||
00000080 # fmt
|
||||
|
||||
00000000 # tx_data
|
||||
|
||||
00000000 # tx_mark
|
||||
|
||||
00000000 # rx_mark
|
||||
|
||||
00000000 # ie reset
|
||||
|
||||
00000000 # ip reset
|
||||
|
||||
00000011 #basic read write
|
||||
|
||||
000000FF
|
||||
|
||||
000000A0
|
||||
|
||||
0000000B
|
||||
|
||||
00000079
|
||||
|
||||
00000000
|
||||
|
||||
000000C0
|
||||
|
||||
00000011
|
||||
|
||||
00000020 #delay registers
|
||||
|
||||
00000032
|
||||
|
||||
00000048
|
||||
|
||||
000000AF
|
||||
|
||||
00000050
|
||||
|
||||
0000006B
|
||||
|
||||
00000011
|
||||
|
||||
00000015
|
||||
|
||||
00000011 #delay1
|
||||
|
||||
00000022
|
||||
|
||||
00000033
|
||||
|
||||
00000044
|
||||
|
||||
0000007B
|
||||
|
||||
00000021
|
||||
|
||||
00000032
|
||||
|
||||
00000043
|
||||
|
||||
00000054
|
||||
|
||||
00000066
|
||||
|
||||
00000077
|
||||
|
||||
00000088
|
||||
|
||||
00000099
|
||||
|
||||
00000066
|
||||
|
||||
00000077
|
||||
|
||||
00000088
|
||||
|
||||
00000099
|
||||
|
||||
00000065
|
||||
|
||||
00000076
|
||||
|
||||
00000087
|
||||
|
||||
00000098
|
||||
|
||||
00000048
|
||||
|
||||
000000DD
|
||||
|
||||
000000CC
|
||||
|
||||
000000BB
|
||||
|
||||
000000AA
|
||||
|
||||
000000DE
|
||||
|
||||
000000CD
|
||||
|
||||
000000BC
|
||||
|
||||
000000AB
|
||||
|
||||
000000F0 #fmt register
|
||||
|
||||
00000000
|
||||
|
||||
00000080
|
||||
|
||||
00000000
|
||||
|
||||
00000080
|
||||
|
||||
000000A8
|
||||
|
||||
000000F8
|
||||
|
||||
00000048
|
||||
|
||||
00000070
|
||||
|
||||
00000000
|
||||
|
||||
00000008
|
||||
|
||||
00000003
|
||||
|
||||
00000017
|
||||
|
||||
0000000F
|
||||
|
||||
0000001F
|
||||
|
||||
00000001 #watermark interrupts
|
||||
|
||||
00000000 #read mip
|
||||
|
||||
00000000 #read tx ip
|
||||
|
||||
00000022 #clear 1 frame from rx fifo
|
||||
|
||||
00000000 # read recieve ip
|
||||
|
||||
00000002 #read recieve ip
|
||||
|
||||
00000000 #read mip
|
||||
|
||||
00000033 #clear frame
|
||||
|
||||
00000000 # read receive ip
|
||||
|
||||
00000044 #clear frame
|
||||
|
||||
00000055 #clear frame
|
||||
|
||||
00000001 #read tx ip
|
||||
|
||||
00000800 #read mip 11
|
||||
|
||||
00000000 #read tx wm 10
|
||||
|
||||
00000000 #read mip 91 9
|
||||
|
||||
00000022 #clear frame 8
|
||||
|
||||
00000000 #read rx ip 7
|
||||
|
||||
00000000 #read mip 94 6
|
||||
|
||||
00000002 #read rx ip 5
|
||||
|
||||
00000800 #read mip 4
|
||||
|
||||
00000033 #clear frame 3
|
||||
|
||||
00000000 #read rx wm 2
|
||||
|
||||
00000000 #read mip 99 1
|
@ -865,6 +865,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
|
||||
|
||||
.equ PLIC_INTPRI_GPIO, 0x0C00000C # GPIO is interrupt 3
|
||||
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
|
||||
.equ PLIC_INTPRI_SPI, 0x0C000018 # SPI in interrupt 6
|
||||
.equ PLIC_INTPENDING0, 0x0C001000 # intPending0 register
|
||||
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
|
||||
.equ PLIC_INTEN10, 0x0C002080 # interrupt enables for context 1 (supervisor mode) sources 31:1
|
||||
@ -877,6 +878,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
|
||||
.4byte PLIC_THRESH1, 7, write32_test # Set PLIC supervisor mode interrupt threshold to 7 to accept no interrupts
|
||||
.4byte PLIC_INTPRI_GPIO, 7, write32_test # Set GPIO to high priority
|
||||
.4byte PLIC_INTPRI_UART, 7, write32_test # Set UART to high priority
|
||||
.4byte PLIC_INTPRI_SPI, 7, write32_test # Set UART to high priority
|
||||
.4byte PLIC_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
|
||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
||||
.endm
|
||||
@ -1028,6 +1030,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C000018 // SPI priority
|
||||
li t3, 7
|
||||
lw t4, 0(t2)
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C002000
|
||||
li t3, 0x0C200004
|
||||
li t4, 0xFFF
|
||||
@ -1038,11 +1046,14 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
sw t6, 0(t2) // restore saved enable status
|
||||
li t2, 0x0C00000C // GPIO priority
|
||||
li t3, 0x0C000028 // UART priority
|
||||
lw t4, 4(sp) // load stored GPIO and UART priority
|
||||
lw t5, 0(sp)
|
||||
addi sp, sp, 8 // restore stack pointer
|
||||
sw t4, 0(t2)
|
||||
sw t5, 0(t3)
|
||||
li t6, 0x0C000018 // SPI priority
|
||||
lw a4, 8(sp) // load stored GPIO prioroty
|
||||
lw t4, 4(sp) // load stored UART priority
|
||||
lw t5, 0(sp) // load stored SPI priority
|
||||
addi sp, sp, 12 // restore stack pointer
|
||||
sw a4, 0(t2)
|
||||
sw t4, 0(t3)
|
||||
sw t5, 0(t6)
|
||||
j test_loop
|
||||
|
||||
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
@ -1128,6 +1139,34 @@ uart_clearmodemintr:
|
||||
lb t2, 0(t2)
|
||||
j test_loop
|
||||
|
||||
spi_data_wait:
|
||||
li t2, 0x10040054
|
||||
sw t4, 0(t2) // set rx watermark level
|
||||
li t2, 0x10040074
|
||||
lw t3, 0(t2) //read ip (interrupt pending register)
|
||||
slli t3, t3, 28
|
||||
srli t3, t3, 28
|
||||
li t2, 0x00000002
|
||||
bge t3, t2, spi_data_ready //branch to done if transmission complete
|
||||
j spi_data_wait //else check again
|
||||
|
||||
spi_data_ready:
|
||||
li t2, 0x10040070
|
||||
li t3, 0x00000000
|
||||
sw t3, 0(t2) //disable rx watermark interrupt
|
||||
j test_loop
|
||||
|
||||
spi_burst_send: //function for loading multiple frames at once to test delays without returning to test loop
|
||||
mv t2, t4
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
j test_loop
|
||||
|
||||
goto_s_mode:
|
||||
// return to address in t3,
|
||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||
|
@ -0,0 +1,511 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-spi
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Naiche Whyte-Aguayo
|
||||
//
|
||||
// Created 2023-02-01
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-32.h"
|
||||
|
||||
RVTEST_ISA("RV32I_Zicsr_Zifencei")
|
||||
RVTEST_CASE(0,"//check ISA:=regex(.*32.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",spi)
|
||||
|
||||
INIT_TESTS
|
||||
|
||||
TRAP_HANDLER m
|
||||
|
||||
j run_test_loop // begin test loop/table tests instead of executing inline code.
|
||||
|
||||
INIT_TEST_TABLE
|
||||
|
||||
END_TESTS
|
||||
|
||||
TEST_STACK_AND_DATA
|
||||
|
||||
.align 2
|
||||
test_cases:
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Test Contents
|
||||
#
|
||||
# Here is where the actual tests are held, or rather, what the actual tests do.
|
||||
# each entry consists of 3 values that will be read in as follows:
|
||||
#
|
||||
# '.4byte [x28 Value], [x29 Value], [x30 value]'
|
||||
# or
|
||||
# '.4byte [address], [value], [test type]'
|
||||
#
|
||||
# The encoding for x30 test type values can be found in the test handler in the framework file
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
.equ SPI, 0x10040000
|
||||
.equ sck_div, (SPI+0x00)
|
||||
.equ sck_mode, (SPI+0x04)
|
||||
.equ cs_id, (SPI+0x10)
|
||||
.equ cs_def, (SPI+0x14)
|
||||
.equ cs_mode, (SPI+0x18)
|
||||
.equ delay0, (SPI+0x28)
|
||||
.equ delay1, (SPI+0x2C)
|
||||
.equ fmt, (SPI+0x40)
|
||||
.equ tx_data, (SPI+0x48)
|
||||
.equ rx_data, (SPI+0x4C)
|
||||
.equ tx_mark, (SPI+0x50)
|
||||
.equ rx_mark, (SPI+0x54)
|
||||
.equ ie, (SPI+0x70)
|
||||
.equ ip, (SPI+0x74)
|
||||
|
||||
test_cases:
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Test Contents
|
||||
#
|
||||
# Here is where the actual tests are held, or rather, what the actual tests do.
|
||||
# each entry consists of 3 values that will be read in as follows:
|
||||
#
|
||||
# '.4byte [x28 Value], [x29 Value], [x30 value]'
|
||||
# or
|
||||
# '.4byte [address], [value], [test type]'
|
||||
#
|
||||
# The encoding for x30 test type values can be found in the test handler in the framework file
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
.equ SPI, 0x10040000
|
||||
.equ sck_div, (SPI+0x00)
|
||||
.equ sck_mode, (SPI+0x04)
|
||||
.equ cs_id, (SPI+0x10)
|
||||
.equ cs_def, (SPI+0x14)
|
||||
.equ cs_mode, (SPI+0x18)
|
||||
.equ delay0, (SPI+0x28)
|
||||
.equ delay1, (SPI+0x2C)
|
||||
.equ fmt, (SPI+0x40)
|
||||
.equ tx_data, (SPI+0x48)
|
||||
.equ rx_data, (SPI+0x4C)
|
||||
.equ tx_mark, (SPI+0x50)
|
||||
.equ rx_mark, (SPI+0x54)
|
||||
.equ ie, (SPI+0x70)
|
||||
.equ ip, (SPI+0x74)
|
||||
|
||||
# =========== Verify all registers reset to correct values ===========
|
||||
|
||||
.4byte sck_div, 0x00000003, read32_test # sck_div reset to 0x3
|
||||
.4byte sck_mode, 0x00000000, read32_test # sck_mode reset to 0x0
|
||||
.4byte cs_id, 0x00000000, read32_test # cs_id reset to 0x0
|
||||
.4byte cs_def, 0x0000000F, read32_test # cs_def reset to 0x1
|
||||
.4byte cs_mode, 0x00000000, read32_test # cs_mode reset to 0x0
|
||||
.4byte delay0, 0x00000101, read32_test # delay0 reset to [31:24] 0x0, [23:16] 0x1, [15:8] 0x0, [7:0] 0x1
|
||||
.4byte delay1, 0x00000001, read32_test # delay1 reset to 0x1
|
||||
.4byte fmt, 0x00000080, read32_test # fmt reset to [31:20] 0x0, [19:16] 0x8, [15:0] 0x0 for non-flash enabled SPI controllers
|
||||
.4byte tx_data, 0x00000000, read32_test # tx_data [30:0] reset to 0x0, [31] read only
|
||||
.4byte tx_mark, 0x00000000, read32_test # tx_mark reset to 0x0 for non-flash enabled controllers
|
||||
.4byte rx_mark, 0x00000000, read32_test # rx_mark reset to 0x0
|
||||
.4byte ie, 0x00000000, read32_test # ie reset to 0x0
|
||||
.4byte ip, 0x00000000, read32_test # ip reset to 0x0
|
||||
|
||||
# =========== Basic read-write ===========
|
||||
|
||||
.4byte tx_data, 0x000000011, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# =========== Different cs_mode, sck_mode, cs_def, sck_div ===========
|
||||
|
||||
# Test sck_div
|
||||
|
||||
.4byte sck_div, 0x00000101, write32_test # set sck_div to 0x101
|
||||
.4byte tx_data, 0x000000FF, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000FF, read32_test # read rx_data
|
||||
|
||||
# Test phase
|
||||
|
||||
.4byte sck_div, 0x00000003, write32_test # reset sck_div to 0x03 so only sck_mode is different
|
||||
.4byte sck_mode, 0x00000001, write32_test # change phase to falling edge
|
||||
.4byte tx_data, 0x000000A0, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000A0, read32_test # read rx_data
|
||||
|
||||
# Test polarity
|
||||
|
||||
.4byte sck_mode, 0x00000000, write32_test # reset sck phase to rising edge
|
||||
.4byte sck_mode, 0x00000002, write32_test # set sck polarity active low
|
||||
.4byte tx_data, 0x0000000B, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x0000000B, read32_test # read rx_data
|
||||
|
||||
# Test chip select polarity
|
||||
|
||||
.4byte sck_mode, 0x00000000, write32_test # reset sck polarity to active high
|
||||
.4byte cs_def, 0x0000000E, write32_test # set cs[0] to inactive low
|
||||
.4byte tx_data, 0x00000079, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000079, read32_test # read rx_data
|
||||
|
||||
# Test chip id
|
||||
|
||||
.4byte cs_def, 0x0000000F, write32_test # reset all cs to active low
|
||||
.4byte cs_id, 0x00000001, write32_test # select cs[1]
|
||||
.4byte tx_data, 0x00000000, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test cs hold mode
|
||||
|
||||
.4byte cs_id, 0x00000000, write32_test # select cs[0]
|
||||
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
|
||||
.4byte tx_data, 0x000000C0, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000C0, read32_test # read rx_data
|
||||
|
||||
# Test cs OFF mode
|
||||
|
||||
.4byte cs_mode, 0x00000003, write32_test # set cs_mode to OFF
|
||||
.4byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# =========== Test delay0 register ===========
|
||||
|
||||
# Test cs-sck delay of 0 with sck phase = 0 (implicit half cycle delay)
|
||||
|
||||
.4byte cs_mode, 0x00000000, write32_test # reset cs_mode to auto, all cs and sck mode settings should be defualt
|
||||
.4byte delay0, 0x0000100, write32_test # set cs-sck delay to 0
|
||||
.4byte tx_data, 0x00000020, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000020, read32_test # read rx_data
|
||||
|
||||
# Test cs-sck delay of 0 with sck phase 1 (no delay)
|
||||
|
||||
.4byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
|
||||
.4byte tx_data, 0x00000032, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000032, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary cs-sck delay (sck phase 1)
|
||||
|
||||
.4byte delay0, 0x00000105, write32_test # set cs-sck delay to 5 cycles
|
||||
.4byte tx_data, 0x00000048, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000048, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary cs-sck delay (sck phase 0)
|
||||
|
||||
.4byte sck_mode, 0x00000000, write32_test # set sck phase to 0
|
||||
.4byte delay0, 0x00000105, write32_test # set cs-sck delay to AF cycles
|
||||
.4byte tx_data, 0x000000AF, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000AF, read32_test # read rx_data
|
||||
|
||||
|
||||
# Test sck-cs delay of 0 with sck phase = 0 (no delay)
|
||||
|
||||
.4byte delay0, 0x00000001, write32_test # set cs-sck delay to 0
|
||||
.4byte tx_data, 0x00000050, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000050, read32_test # read rx_data
|
||||
|
||||
# Test sck-cs delay of 0 with sck phase 1 (implicit half cycle delay)
|
||||
|
||||
.4byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
|
||||
.4byte tx_data, 0x0000006B, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x0000006B, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary sck-cs delay (sck phase 1)
|
||||
|
||||
.4byte delay0, 0x00000501, write32_test # set cs-sck delay to A5 cycles
|
||||
.4byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary sck-cs delay (sck phase 0)
|
||||
|
||||
.4byte sck_mode, 0x00000000, write32_test # set sck phase to 0
|
||||
.4byte delay0, 0x00000501, write32_test # set cs-sck delay to 5 cycles
|
||||
.4byte tx_data, 0x00000015, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000015, read32_test # read rx_data
|
||||
|
||||
# =========== Test delay1 register ===========
|
||||
|
||||
# Test inter cs delay
|
||||
|
||||
|
||||
.4byte delay0, 0x00000101, write32_test # reset delay0 register
|
||||
.4byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
|
||||
.4byte tx_data, 0x44332211, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000011, read32_test
|
||||
.4byte rx_data, 0x00000022, read32_test
|
||||
.4byte rx_data, 0x00000033, read32_test
|
||||
.4byte rx_data, 0x00000044, read32_test
|
||||
|
||||
#test long inter_cs delay
|
||||
|
||||
.4byte delay1, 0x000000A5, write32_test
|
||||
.4byte tx_data, 0x0000007B, write32_test
|
||||
.4byte 0x0, 0x00000000, spi_data_wait
|
||||
.4byte rx_data, 0x0000007B, read32_test
|
||||
|
||||
|
||||
# Test inter_cs delay set to 0
|
||||
|
||||
.4byte delay1, 0x00000000, write32_test # set inter_cs delay to 5
|
||||
.4byte tx_data, 0x54433221, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000021, read32_test
|
||||
.4byte rx_data, 0x00000032, read32_test
|
||||
.4byte rx_data, 0x00000043, read32_test
|
||||
.4byte rx_data, 0x00000054, read32_test
|
||||
|
||||
|
||||
# Test inter_xfr delay of 0 (maybe change behavior to half-period instead of period)
|
||||
|
||||
.4byte delay1, 0x00000001, write32_test # reset inter_cs delay to 1
|
||||
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
|
||||
.4byte tx_data, 0x99887766, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000066, read32_test
|
||||
.4byte rx_data, 0x00000077, read32_test
|
||||
.4byte rx_data, 0x00000088, read32_test
|
||||
.4byte rx_data, 0x00000099, read32_test
|
||||
|
||||
# Test inter_xfr delay 0 with phase = 1
|
||||
.4byte sck_mode, 0x00000001, write32_test
|
||||
.4byte tx_data, 0x99887766, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait
|
||||
.4byte rx_data, 0x00000066, read32_test
|
||||
.4byte rx_data, 0x00000077, read32_test
|
||||
.4byte rx_data, 0x00000088, read32_test
|
||||
.4byte rx_data, 0x00000099, read32_test
|
||||
|
||||
|
||||
# Test arbitrary inter_xfr delay
|
||||
|
||||
.4byte delay1, 0x00000501, write32_test # set inter_xfr delay to 5
|
||||
.4byte sck_mode, 0x00000001, write32_test
|
||||
.4byte tx_data, 0x98877665, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000065, read32_test
|
||||
.4byte rx_data, 0x00000076, read32_test
|
||||
.4byte rx_data, 0x00000087, read32_test
|
||||
.4byte rx_data, 0x00000098, read32_test
|
||||
|
||||
# test long inter_xfr delay
|
||||
.4byte delay1, 0x0000A501, write32_test
|
||||
.4byte tx_data, 0x00000048, write32_test
|
||||
.4byte 0x0, 0x00000000, spi_data_wait
|
||||
.4byte rx_data, 0x00000048, read32_test
|
||||
|
||||
# Test cs-sck delay with cs_mode = HOLD
|
||||
|
||||
.4byte delay1, 0x00000001, write32_test # set inter_xfr delay to 0
|
||||
.4byte delay0, 0x00000105, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
|
||||
.4byte tx_data, 0xAABBCCDD, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000DD, read32_test # read rx_data
|
||||
.4byte rx_data, 0x000000CC, read32_test
|
||||
.4byte rx_data, 0x000000BB, read32_test
|
||||
.4byte rx_data, 0x000000AA, read32_test
|
||||
|
||||
# Test sck-cs delay cs_mode = HOLD
|
||||
|
||||
.4byte delay0, 0x00000501, write32_test # set sck-cs delay to 5 (should have no effect because cs is never inactive)
|
||||
.4byte tx_data, 0xABBCCDDE, spi_burst_send # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000DE, read32_test # read rx_data
|
||||
.4byte rx_data, 0x000000CD, read32_test
|
||||
.4byte rx_data, 0x000000BC, read32_test
|
||||
.4byte rx_data, 0x000000AB, read32_test
|
||||
|
||||
# =========== Test frame format (fmt) register ===========
|
||||
|
||||
# Test frame length of 4
|
||||
|
||||
.4byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||
.4byte delay0, 0x00000101, write32_test # reset delay0 register
|
||||
.4byte sck_mode, 0x00000000, write32_test #reset sckmode register
|
||||
.4byte cs_mode, 0x00000000, write32_test # set cs_mode to AUTO
|
||||
.4byte fmt, 0x00000040, write32_test # set frame length to 4
|
||||
.4byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000F0, read32_test # read rx_data
|
||||
|
||||
# Test frame length of 0
|
||||
|
||||
#.4byte fmt, 0x00000000, write32_test # set frame length to 4
|
||||
#.4byte tx_data, 0x00000077, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x0101, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x00000077, read32_test # read rx_data
|
||||
|
||||
# test frame length 1 burst
|
||||
.4byte fmt, 0x00000010, write32_test
|
||||
.4byte tx_data, 0x80008000, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait
|
||||
.4byte rx_data, 0x00000000, read32_test
|
||||
.4byte rx_data, 0x00000080, read32_test
|
||||
.4byte rx_data, 0x00000000, read32_test
|
||||
.4byte rx_data, 0x00000080, read32_test
|
||||
|
||||
|
||||
# Test big endian with frame length = 5
|
||||
|
||||
.4byte fmt, 0x00000050, write32_test # set frame length to 5, big endian
|
||||
.4byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x000000A8, read32_test # read rx_data
|
||||
|
||||
# Test big endian burst with frame length = 5
|
||||
|
||||
.4byte tx_data, 0x03774FFF, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait
|
||||
.4byte rx_data, 0x000000F8, read32_test
|
||||
.4byte rx_data, 0x00000048, read32_test
|
||||
.4byte rx_data, 0x00000070, read32_test
|
||||
.4byte rx_data, 0x00000000, read32_test
|
||||
|
||||
|
||||
|
||||
|
||||
# Test little endian with frame length = 5
|
||||
|
||||
.4byte fmt, 0x00000054, write32_test # set frame length to 5, little-endian
|
||||
.4byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
|
||||
.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.4byte rx_data, 0x00000008, read32_test # read rx_data -> 08
|
||||
|
||||
#test little endian burst with frame length = 5
|
||||
|
||||
.4byte tx_data, 0xFF4F7703, spi_burst_send
|
||||
.4byte 0x0, 0x00000003, spi_data_wait
|
||||
.4byte rx_data, 0x00000003, read32_test #03
|
||||
.4byte rx_data, 0x00000017, read32_test #17
|
||||
.4byte rx_data, 0x0000000F, read32_test #0F
|
||||
.4byte rx_data, 0x0000001F, read32_test #1F
|
||||
|
||||
# Test dual SPI protocol, frame length = 8, big endian
|
||||
|
||||
#.4byte fmt, 0x00000081, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x000000C8, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol, frame length = 4
|
||||
|
||||
#.4byte fmt, 0x00000041, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x000000A2, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x000000A0, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol, frame length = 5
|
||||
|
||||
#.4byte fmt, 0x00000051, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x00000075, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x00000074, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol burst, frame length = 5
|
||||
#.4byte tx_data, 0x30733FFF, spi_burst_send
|
||||
#.4byte 0x0, 0x00000003, spi_data_wait
|
||||
#.4byte rx_data, 0x000000FC, read32_test
|
||||
#.4byte rx_data, 0x0000003C, read32_test
|
||||
#.4byte rx_data, 0x00000070, read32_test
|
||||
#.4byte rx_data, 0x00000030, read32_test
|
||||
|
||||
# Test quad SPI protocol, frame length = 5
|
||||
|
||||
#.4byte fmt, 0x00000052, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x0000003F, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x0000003F, read32_test # read rx_data
|
||||
|
||||
# Test quad SPI protocol, frame length = 4
|
||||
|
||||
#.4byte fmt, 0x00000042, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x0000000F, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test quad SPI protocol, frame length = 8
|
||||
|
||||
#.4byte fmt, 0x00000082, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.4byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
|
||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.4byte rx_data, 0x000000F0, read32_test # read rx_data
|
||||
|
||||
# =========== Test watermark interrupts ===========
|
||||
|
||||
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||
# rx fifo > rx mark
|
||||
|
||||
SETUP_PLIC
|
||||
|
||||
.4byte fmt, 0x00000080, write32_test # reset fmt register
|
||||
.4byte tx_mark, 0x00000004, write32_test # set transmit watermark to 4
|
||||
#.4byte ie, 0x00000000, write32_test # enable transmit interrupt
|
||||
.4byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
|
||||
.4byte 0x0, 0x00000000, readmip_test
|
||||
.4byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||
.4byte ip, 0x00000000, read32_test # tx watermark interupt should be off
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
|
||||
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
|
||||
|
||||
.4byte tx_mark, 0x00000000, write32_test # set tx_mark to 0
|
||||
.4byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
|
||||
.4byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
|
||||
#.4byte ie, 0x0000002, write32_test # enable receive interrupts
|
||||
.4byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
|
||||
.4byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
|
||||
.4byte ip, 0x00000002, read32_test # recieve interrupt should be high
|
||||
.4byte 0x0, 0x00000000, readmip_test
|
||||
.4byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
|
||||
.4byte ip, 0x00000000, read32_test # receive interrupt should be low
|
||||
.4byte rx_data, 0x00000044, read32_test
|
||||
.4byte rx_data, 0x00000055, read32_test # clear rx fifo
|
||||
|
||||
|
||||
.4byte tx_mark, 0x00000004, write32_test # set transmit watermark to 4
|
||||
.4byte ie, 0x00000001, write32_test # enable transmit interrupt
|
||||
.4byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
|
||||
.4byte 0x0, 0x00000800, readmip_test
|
||||
.4byte ie, 0x00000000, write32_test #turn off tx mark
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts
|
||||
.4byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||
.4byte ie, 0x00000001, write32_test #turn tx mark back on
|
||||
.4byte tx_mark, 0x00000001, write32_test
|
||||
.4byte ip, 0x00000000, read32_test # tx watermark interupt should be off
|
||||
.4byte 0x0, 0x00000000, readmip_test
|
||||
.4byte ie, 0x00000000, write32_test # disable tx intr
|
||||
.4byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
|
||||
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
|
||||
|
||||
.4byte tx_mark, 0x00000000, write32_test
|
||||
.4byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
|
||||
.4byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
|
||||
.4byte ie, 0x0000002, write32_test # enable receive interrupts
|
||||
.4byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
|
||||
.4byte 0x0, 0x00000000, readmip_test
|
||||
.4byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
|
||||
.4byte ip, 0x00000002, read32_test # recieve interrupt should be high
|
||||
.4byte 0x0, 0x00000800, readmip_test
|
||||
.4byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
|
||||
.4byte 0x0, 0x00000000, claim_m_plic_interrupts
|
||||
.4byte ip, 0x00000000, read32_test # receive interrupt should be low
|
||||
.4byte 0x0, 0x00000000, readmip_test
|
||||
|
||||
.4byte 0x0, 0x0, terminate_test
|
@ -55,6 +55,9 @@ target_tests_nosim = \
|
||||
WALLY-trap-s-01 \
|
||||
WALLY-trap-u-01 \
|
||||
WALLY-status-fp-enabled-01 \
|
||||
WALLY-spi-01 \
|
||||
WALLY-gpio-01 \
|
||||
WALLY-uart-01 \
|
||||
WALLY-wfi-01 \
|
||||
WALLY-cbom-01 \
|
||||
WALLY-cboz-01 \
|
||||
|
@ -0,0 +1,194 @@
|
||||
00000003 # reset tests sck_div
|
||||
00000000
|
||||
00000000 # sck_mode
|
||||
00000000
|
||||
00000000 # cs_id
|
||||
00000000
|
||||
0000000F # cs_def
|
||||
00000000
|
||||
00000000 # cs_mode
|
||||
00000000
|
||||
00000101 # delay 0
|
||||
00000000
|
||||
00000001 # delay 1
|
||||
00000000
|
||||
00000080 # fmt
|
||||
00000000
|
||||
00000000 # tx_data
|
||||
00000000
|
||||
00000000 # tx_mark
|
||||
00000000
|
||||
00000000 # rx_mark
|
||||
00000000
|
||||
00000000 # ie reset
|
||||
00000000
|
||||
00000000 # ip reset
|
||||
00000000
|
||||
00000011 #basic read write
|
||||
00000000
|
||||
000000FF
|
||||
00000000
|
||||
000000A0
|
||||
00000000
|
||||
0000000B
|
||||
00000000
|
||||
00000079
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
000000C0
|
||||
00000000
|
||||
00000011
|
||||
00000000
|
||||
00000020 #delay registers
|
||||
00000000
|
||||
00000032
|
||||
00000000
|
||||
00000048
|
||||
00000000
|
||||
000000AF
|
||||
00000000
|
||||
00000050
|
||||
00000000
|
||||
0000006B
|
||||
00000000
|
||||
00000011
|
||||
00000000
|
||||
00000015
|
||||
00000000
|
||||
00000011 #delay1
|
||||
00000000
|
||||
00000022
|
||||
00000000
|
||||
00000033
|
||||
00000000
|
||||
00000044
|
||||
00000000
|
||||
0000007B
|
||||
00000000
|
||||
00000021
|
||||
00000000
|
||||
00000032
|
||||
00000000
|
||||
00000043
|
||||
00000000
|
||||
00000054
|
||||
00000000
|
||||
00000066
|
||||
00000000
|
||||
00000077
|
||||
00000000
|
||||
00000088
|
||||
00000000
|
||||
00000099
|
||||
00000000
|
||||
00000066
|
||||
00000000
|
||||
00000077
|
||||
00000000
|
||||
00000088
|
||||
00000000
|
||||
00000099
|
||||
00000000
|
||||
00000065
|
||||
00000000
|
||||
00000076
|
||||
00000000
|
||||
00000087
|
||||
00000000
|
||||
00000098
|
||||
00000000
|
||||
00000048
|
||||
00000000
|
||||
000000DD
|
||||
00000000
|
||||
000000CC
|
||||
00000000
|
||||
000000BB
|
||||
00000000
|
||||
000000AA
|
||||
00000000
|
||||
000000DE
|
||||
00000000
|
||||
000000CD
|
||||
00000000
|
||||
000000BC
|
||||
00000000
|
||||
000000AB
|
||||
00000000
|
||||
000000F0 #fmt register
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000080
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000080
|
||||
00000000
|
||||
000000A8
|
||||
00000000
|
||||
000000F8
|
||||
00000000
|
||||
00000048
|
||||
00000000
|
||||
00000070
|
||||
00000000
|
||||
00000000
|
||||
00000000
|
||||
00000008
|
||||
00000000
|
||||
00000003
|
||||
00000000
|
||||
00000017
|
||||
00000000
|
||||
0000000F
|
||||
00000000
|
||||
0000001F
|
||||
00000000
|
||||
00000001 #watermark interrupts
|
||||
00000000
|
||||
00000000 #read mip
|
||||
00000000
|
||||
00000000 #read tx ip
|
||||
00000000
|
||||
00000022 #clear 1 frame from rx fifo
|
||||
00000000
|
||||
00000000 # read recieve ip
|
||||
00000000
|
||||
00000002 #read recieve ip
|
||||
00000000
|
||||
00000000 #read mip
|
||||
00000000
|
||||
00000033 #clear frame
|
||||
00000000
|
||||
00000000 # read receive ip
|
||||
00000000
|
||||
00000044 #clear frame
|
||||
00000000
|
||||
00000055 #clear frame
|
||||
00000000
|
||||
00000001 #read tx ip
|
||||
00000000
|
||||
00000800 #read mip
|
||||
00000000
|
||||
00000000 #read tx wm
|
||||
00000000
|
||||
00000000 #read mip 91
|
||||
00000000
|
||||
00000022 #clear frame
|
||||
00000000
|
||||
00000000 #read rx ip
|
||||
00000000
|
||||
00000000 #read mip 94
|
||||
00000000
|
||||
00000002 #read rx ip
|
||||
00000000
|
||||
00000800 #read mip
|
||||
00000000
|
||||
00000033 #clear frame
|
||||
00000000
|
||||
00000000 #read rx wm
|
||||
00000000
|
||||
00000000 #read mip 99
|
||||
00000000
|
@ -884,6 +884,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
|
||||
|
||||
.equ PLIC_INTPRI_GPIO, 0x0C00000C # GPIO is interrupt 3
|
||||
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
|
||||
.equ PLIC_INTPRI_SPI, 0x0C000018 # SPI in interrupt 6
|
||||
.equ PLIC_INTPENDING0, 0x0C001000 # intPending0 register
|
||||
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
|
||||
.equ PLIC_INTEN10, 0x0C002080 # interrupt enables for context 1 (supervisor mode) sources 31:1
|
||||
@ -896,6 +897,7 @@ trap_handler_end_\MODE\(): // place to jump to so we can skip the trap handler a
|
||||
.8byte PLIC_THRESH1, 7, write32_test # Set PLIC supervisor mode interrupt threshold to 7 to accept no interrupts
|
||||
.8byte PLIC_INTPRI_GPIO, 7, write32_test # Set GPIO to high priority
|
||||
.8byte PLIC_INTPRI_UART, 7, write32_test # Set UART to high priority
|
||||
.8byte PLIC_INTPRI_SPI, 7, write32_test # Set SPI to high priority
|
||||
.8byte PLIC_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
|
||||
.8byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
||||
.endm
|
||||
@ -1065,6 +1067,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C000018 // SPI priority
|
||||
li t3, 7
|
||||
lw t4, 0(t2)
|
||||
sw t3, 0(t2)
|
||||
sw t4, -4(sp)
|
||||
addi sp, sp, -4
|
||||
li t2, 0x0C002000
|
||||
li t3, 0x0C200004
|
||||
li t4, 0xFFF
|
||||
@ -1075,11 +1083,14 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
sw t6, 0(t2) // restore saved enable status
|
||||
li t2, 0x0C00000C // GPIO priority
|
||||
li t3, 0x0C000028 // UART priority
|
||||
lw t4, 4(sp) // load stored GPIO and UART priority
|
||||
lw t5, 0(sp)
|
||||
addi sp, sp, 8 // restore stack pointer
|
||||
sw t4, 0(t2)
|
||||
sw t5, 0(t3)
|
||||
li t6, 0x0C000018 // SPI priority
|
||||
lw a4, 8(sp) // load stored GPIO prioroty
|
||||
lw t4, 4(sp) // load stored UART priority
|
||||
lw t5, 0(sp) // load stored SPI priority
|
||||
addi sp, sp, 12 // restore stack pointer
|
||||
sw a4, 0(t2)
|
||||
sw t4, 0(t3)
|
||||
sw t5, 0(t6)
|
||||
j test_loop
|
||||
|
||||
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||
@ -1165,6 +1176,34 @@ uart_clearmodemintr:
|
||||
lb t2, 0(t2)
|
||||
j test_loop
|
||||
|
||||
spi_data_wait:
|
||||
li t2, 0x10040054
|
||||
sw t4, 0(t2) // set rx watermark level
|
||||
li t2, 0x10040074
|
||||
lw t3, 0(t2) //read ip (interrupt pending register)
|
||||
slli t3, t3, 56
|
||||
srli t3, t3, 56
|
||||
li t2, 0x00000002
|
||||
bge t3, t2, spi_data_ready //branch to done if transmission complete
|
||||
j spi_data_wait //else check again
|
||||
|
||||
spi_data_ready:
|
||||
li t2, 0x10040070
|
||||
li t3, 0x00000000
|
||||
sw t3, 0(t2) //disable rx watermark interrupt
|
||||
j test_loop
|
||||
|
||||
spi_burst_send: //function for loading multiple frames at once to test delays without returning to test loop
|
||||
mv t2, t4
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
srli t2, t2, 8
|
||||
sw t2, 0(t3)
|
||||
j test_loop
|
||||
|
||||
goto_s_mode:
|
||||
// return to address in t3,
|
||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||
|
@ -0,0 +1,478 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-spi
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Naiche Whyte-Aguayo
|
||||
//
|
||||
// Created 2023-02-01
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-64.h"
|
||||
|
||||
RVTEST_ISA("RV64I_Zicsr_Zifencei")
|
||||
RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*); def Drvtest_mtrap_routine=True;def TEST_CASE_1=True;def NO_SAIL=True;",spi)
|
||||
|
||||
INIT_TESTS
|
||||
|
||||
TRAP_HANDLER m
|
||||
|
||||
j run_test_loop // begin test loop/table tests instead of executing inline code.
|
||||
|
||||
INIT_TEST_TABLE
|
||||
|
||||
END_TESTS
|
||||
|
||||
TEST_STACK_AND_DATA
|
||||
|
||||
.align 3
|
||||
test_cases:
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Test Contents
|
||||
#
|
||||
# Here is where the actual tests are held, or rather, what the actual tests do.
|
||||
# each entry consists of 3 values that will be read in as follows:
|
||||
#
|
||||
# '.8byte [x28 Value], [x29 Value], [x30 value]'
|
||||
# or
|
||||
# '.8byte [address], [value], [test type]'
|
||||
#
|
||||
# The encoding for x30 test type values can be found in the test handler in the framework file
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
.equ SPI, 0x10040000
|
||||
.equ sck_div, (SPI+0x00)
|
||||
.equ sck_mode, (SPI+0x04)
|
||||
.equ cs_id, (SPI+0x10)
|
||||
.equ cs_def, (SPI+0x14)
|
||||
.equ cs_mode, (SPI+0x18)
|
||||
.equ delay0, (SPI+0x28)
|
||||
.equ delay1, (SPI+0x2C)
|
||||
.equ fmt, (SPI+0x40)
|
||||
.equ tx_data, (SPI+0x48)
|
||||
.equ rx_data, (SPI+0x4C)
|
||||
.equ tx_mark, (SPI+0x50)
|
||||
.equ rx_mark, (SPI+0x54)
|
||||
.equ ie, (SPI+0x70)
|
||||
.equ ip, (SPI+0x74)
|
||||
|
||||
# =========== Verify all registers reset to correct values ===========
|
||||
|
||||
.8byte sck_div, 0x00000003, read32_test # sck_div reset to 0x3
|
||||
.8byte sck_mode, 0x00000000, read32_test # sck_mode reset to 0x0
|
||||
.8byte cs_id, 0x00000000, read32_test # cs_id reset to 0x0
|
||||
.8byte cs_def, 0x0000000F, read32_test # cs_def reset to 0x1
|
||||
.8byte cs_mode, 0x00000000, read32_test # cs_mode reset to 0x0
|
||||
.8byte delay0, 0x00000101, read32_test # delay0 reset to [31:24] 0x0, [23:16] 0x1, [15:8] 0x0, [7:0] 0x1
|
||||
.8byte delay1, 0x00000001, read32_test # delay1 reset to 0x1
|
||||
.8byte fmt, 0x00000080, read32_test # fmt reset to [31:20] 0x0, [19:16] 0x8, [15:0] 0x0 for non-flash enabled SPI controllers
|
||||
.8byte tx_data, 0x00000000, read32_test # tx_data [30:0] reset to 0x0, [31] read only
|
||||
.8byte tx_mark, 0x00000000, read32_test # tx_mark reset to 0x0 for non-flash enabled controllers
|
||||
.8byte rx_mark, 0x00000000, read32_test # rx_mark reset to 0x0
|
||||
.8byte ie, 0x00000000, read32_test # ie reset to 0x0
|
||||
.8byte ip, 0x00000000, read32_test # ip reset to 0x0
|
||||
|
||||
# =========== Basic read-write ===========
|
||||
|
||||
.8byte tx_data, 0x000000011, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# =========== Different cs_mode, sck_mode, cs_def, sck_div ===========
|
||||
|
||||
# Test sck_div
|
||||
|
||||
.8byte sck_div, 0x00000101, write32_test # set sck_div to 0x101
|
||||
.8byte tx_data, 0x000000FF, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000FF, read32_test # read rx_data
|
||||
|
||||
# Test phase
|
||||
|
||||
.8byte sck_div, 0x00000003, write32_test # reset sck_div to 0x03 so only sck_mode is different
|
||||
.8byte sck_mode, 0x00000001, write32_test # change phase to falling edge
|
||||
.8byte tx_data, 0x000000A0, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000A0, read32_test # read rx_data
|
||||
|
||||
# Test polarity
|
||||
|
||||
.8byte sck_mode, 0x00000000, write32_test # reset sck phase to rising edge
|
||||
.8byte sck_mode, 0x00000002, write32_test # set sck polarity active low
|
||||
.8byte tx_data, 0x0000000B, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x0000000B, read32_test # read rx_data
|
||||
|
||||
# Test chip select polarity
|
||||
|
||||
.8byte sck_mode, 0x00000000, write32_test # reset sck polarity to active high
|
||||
.8byte cs_def, 0x0000000E, write32_test # set cs[0] to inactive low
|
||||
.8byte tx_data, 0x00000079, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000079, read32_test # read rx_data
|
||||
|
||||
# Test chip id
|
||||
|
||||
.8byte cs_def, 0x0000000F, write32_test # reset all cs to active low
|
||||
.8byte cs_id, 0x00000001, write32_test # select cs[1]
|
||||
.8byte tx_data, 0x00000000, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test cs hold mode
|
||||
|
||||
.8byte cs_id, 0x00000000, write32_test # select cs[0]
|
||||
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
|
||||
.8byte tx_data, 0x000000C0, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000C0, read32_test # read rx_data
|
||||
|
||||
# Test cs OFF mode
|
||||
|
||||
.8byte cs_mode, 0x00000003, write32_test # set cs_mode to OFF
|
||||
.8byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# =========== Test delay0 register ===========
|
||||
|
||||
# Test cs-sck delay of 0 with sck phase = 0 (implicit half cycle delay)
|
||||
|
||||
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode to auto, all cs and sck mode settings should be defualt
|
||||
.8byte delay0, 0x0000100, write32_test # set cs-sck delay to 0
|
||||
.8byte tx_data, 0x00000020, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000020, read32_test # read rx_data
|
||||
|
||||
# Test cs-sck delay of 0 with sck phase 1 (no delay)
|
||||
|
||||
.8byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
|
||||
.8byte tx_data, 0x00000032, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000032, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary cs-sck delay (sck phase 1)
|
||||
|
||||
.8byte delay0, 0x00000105, write32_test # set cs-sck delay to 5 cycles
|
||||
.8byte tx_data, 0x00000048, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000048, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary cs-sck delay (sck phase 0)
|
||||
|
||||
.8byte sck_mode, 0x00000000, write32_test # set sck phase to 0
|
||||
.8byte delay0, 0x00000105, write32_test # set cs-sck delay to AF cycles
|
||||
.8byte tx_data, 0x000000AF, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000AF, read32_test # read rx_data
|
||||
|
||||
|
||||
# Test sck-cs delay of 0 with sck phase = 0 (no delay)
|
||||
|
||||
.8byte delay0, 0x00000001, write32_test # set cs-sck delay to 0
|
||||
.8byte tx_data, 0x00000050, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000050, read32_test # read rx_data
|
||||
|
||||
# Test sck-cs delay of 0 with sck phase 1 (implicit half cycle delay)
|
||||
|
||||
.8byte sck_mode, 0x00000001, write32_test # set sck_mode[0] to 1 (sck phase = 1)
|
||||
.8byte tx_data, 0x0000006B, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x0000006B, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary sck-cs delay (sck phase 1)
|
||||
|
||||
.8byte delay0, 0x00000501, write32_test # set cs-sck delay to A5 cycles
|
||||
.8byte tx_data, 0x00000011, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000011, read32_test # read rx_data
|
||||
|
||||
# Test arbitrary sck-cs delay (sck phase 0)
|
||||
|
||||
.8byte sck_mode, 0x00000000, write32_test # set sck phase to 0
|
||||
.8byte delay0, 0x00000501, write32_test # set cs-sck delay to 5 cycles
|
||||
.8byte tx_data, 0x00000015, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000015, read32_test # read rx_data
|
||||
|
||||
# =========== Test delay1 register ===========
|
||||
|
||||
# Test inter cs delay
|
||||
|
||||
|
||||
.8byte delay0, 0x00000101, write32_test # reset delay0 register
|
||||
.8byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
|
||||
.8byte tx_data, 0x44332211, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000011, read32_test
|
||||
.8byte rx_data, 0x00000022, read32_test
|
||||
.8byte rx_data, 0x00000033, read32_test
|
||||
.8byte rx_data, 0x00000044, read32_test
|
||||
|
||||
#test long inter_cs delay
|
||||
|
||||
.8byte delay1, 0x000000A5, write32_test
|
||||
.8byte tx_data, 0x0000007B, write32_test
|
||||
.8byte 0x0, 0x00000000, spi_data_wait
|
||||
.8byte rx_data, 0x0000007B, read32_test
|
||||
|
||||
|
||||
# Test inter_cs delay set to 0
|
||||
|
||||
.8byte delay1, 0x00000000, write32_test # set inter_cs delay to 5
|
||||
.8byte tx_data, 0x54433221, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000021, read32_test
|
||||
.8byte rx_data, 0x00000032, read32_test
|
||||
.8byte rx_data, 0x00000043, read32_test
|
||||
.8byte rx_data, 0x00000054, read32_test
|
||||
|
||||
|
||||
# Test inter_xfr delay of 0 (maybe change behavior to half-period instead of period)
|
||||
|
||||
.8byte delay1, 0x00000001, write32_test # reset inter_cs delay to 1
|
||||
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to HOLD
|
||||
.8byte tx_data, 0x99887766, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000066, read32_test
|
||||
.8byte rx_data, 0x00000077, read32_test
|
||||
.8byte rx_data, 0x00000088, read32_test
|
||||
.8byte rx_data, 0x00000099, read32_test
|
||||
|
||||
# Test inter_xfr delay 0 with phase = 1
|
||||
.8byte sck_mode, 0x00000001, write32_test
|
||||
.8byte tx_data, 0x99887766, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait
|
||||
.8byte rx_data, 0x00000066, read32_test
|
||||
.8byte rx_data, 0x00000077, read32_test
|
||||
.8byte rx_data, 0x00000088, read32_test
|
||||
.8byte rx_data, 0x00000099, read32_test
|
||||
|
||||
|
||||
# Test arbitrary inter_xfr delay
|
||||
|
||||
.8byte delay1, 0x00000501, write32_test # set inter_xfr delay to 5
|
||||
.8byte sck_mode, 0x00000001, write32_test
|
||||
.8byte tx_data, 0x98877665, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000065, read32_test
|
||||
.8byte rx_data, 0x00000076, read32_test
|
||||
.8byte rx_data, 0x00000087, read32_test
|
||||
.8byte rx_data, 0x00000098, read32_test
|
||||
|
||||
# test long inter_xfr delay
|
||||
.8byte delay1, 0x0000A501, write32_test
|
||||
.8byte tx_data, 0x00000048, write32_test
|
||||
.8byte 0x0, 0x00000000, spi_data_wait
|
||||
.8byte rx_data, 0x00000048, read32_test
|
||||
|
||||
# Test cs-sck delay with cs_mode = HOLD
|
||||
|
||||
.8byte delay1, 0x00000001, write32_test # set inter_xfr delay to 0
|
||||
.8byte delay0, 0x00000105, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
|
||||
.8byte tx_data, 0xAABBCCDD, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000DD, read32_test # read rx_data
|
||||
.8byte rx_data, 0x000000CC, read32_test
|
||||
.8byte rx_data, 0x000000BB, read32_test
|
||||
.8byte rx_data, 0x000000AA, read32_test
|
||||
|
||||
# Test sck-cs delay cs_mode = HOLD
|
||||
|
||||
.8byte delay0, 0x00000501, write32_test # set sck-cs delay to 5 (should have no effect because cs is never inactive)
|
||||
.8byte tx_data, 0xABBCCDDE, spi_burst_send # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000DE, read32_test # read rx_data
|
||||
.8byte rx_data, 0x000000CD, read32_test
|
||||
.8byte rx_data, 0x000000BC, read32_test
|
||||
.8byte rx_data, 0x000000AB, read32_test
|
||||
|
||||
# =========== Test frame format (fmt) register ===========
|
||||
|
||||
# Test frame length of 4
|
||||
|
||||
.8byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||
.8byte delay0, 0x00000101, write32_test # reset delay0 register
|
||||
.8byte sck_mode, 0x00000000, write32_test #reset sckmode register
|
||||
.8byte cs_mode, 0x00000000, write32_test # set cs_mode to AUTO
|
||||
.8byte fmt, 0x00000040, write32_test # set frame length to 4
|
||||
.8byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000F0, read32_test # read rx_data
|
||||
|
||||
# Test frame length of 0
|
||||
|
||||
#.8byte fmt, 0x00000000, write32_test # set frame length to 4
|
||||
#.8byte tx_data, 0x00000077, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x0101, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x00000077, read32_test # read rx_data
|
||||
|
||||
# test frame length 1 burst
|
||||
.8byte fmt, 0x00000010, write32_test
|
||||
.8byte tx_data, 0x80008000, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait
|
||||
.8byte rx_data, 0x00000000, read32_test
|
||||
.8byte rx_data, 0x00000080, read32_test
|
||||
.8byte rx_data, 0x00000000, read32_test
|
||||
.8byte rx_data, 0x00000080, read32_test
|
||||
|
||||
|
||||
# Test big endian with frame length = 5
|
||||
|
||||
.8byte fmt, 0x00000050, write32_test # set frame length to 5, big endian
|
||||
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x000000A8, read32_test # read rx_data
|
||||
|
||||
# Test big endian burst with frame length = 5
|
||||
|
||||
.8byte tx_data, 0x03774FFF, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait
|
||||
.8byte rx_data, 0x000000F8, read32_test
|
||||
.8byte rx_data, 0x00000048, read32_test
|
||||
.8byte rx_data, 0x00000070, read32_test
|
||||
.8byte rx_data, 0x00000000, read32_test
|
||||
|
||||
|
||||
|
||||
|
||||
# Test little endian with frame length = 5
|
||||
|
||||
.8byte fmt, 0x00000054, write32_test # set frame length to 5, little-endian
|
||||
.8byte tx_data, 0x000000A8, write32_test # place 8'h11 into tx_data
|
||||
.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
.8byte rx_data, 0x00000008, read32_test # read rx_data -> 08
|
||||
|
||||
#test little endian burst with frame length = 5
|
||||
|
||||
.8byte tx_data, 0xFF4F7703, spi_burst_send
|
||||
.8byte 0x0, 0x00000003, spi_data_wait
|
||||
.8byte rx_data, 0x00000003, read32_test #03
|
||||
.8byte rx_data, 0x00000017, read32_test #17
|
||||
.8byte rx_data, 0x0000000F, read32_test #0F
|
||||
.8byte rx_data, 0x0000001F, read32_test #1F
|
||||
|
||||
# Test dual SPI protocol, frame length = 8, big endian
|
||||
|
||||
#.8byte fmt, 0x00000081, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x000000C8, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol, frame length = 4
|
||||
|
||||
#.8byte fmt, 0x00000041, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x000000A2, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x000000A0, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol, frame length = 5
|
||||
|
||||
#.8byte fmt, 0x00000051, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x00000075, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x00000074, read32_test # read rx_data
|
||||
|
||||
# Test dual SPI protocol burst, frame length = 5
|
||||
#.8byte tx_data, 0x30733FFF, spi_burst_send
|
||||
#.8byte 0x0, 0x00000003, spi_data_wait
|
||||
#.8byte rx_data, 0x000000FC, read32_test
|
||||
#.8byte rx_data, 0x0000003C, read32_test
|
||||
#.8byte rx_data, 0x00000070, read32_test
|
||||
#.8byte rx_data, 0x00000030, read32_test
|
||||
|
||||
# Test quad SPI protocol, frame length = 5
|
||||
|
||||
#.8byte fmt, 0x00000052, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x0000003F, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x0000003F, read32_test # read rx_data
|
||||
|
||||
# Test quad SPI protocol, frame length = 4
|
||||
|
||||
#.8byte fmt, 0x00000042, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x0000000F, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x00000000, read32_test # read rx_data
|
||||
|
||||
# Test quad SPI protocol, frame length = 8
|
||||
|
||||
#.8byte fmt, 0x00000082, write32_test # set frame length to 8, big-endian, dual SPI
|
||||
#.8byte tx_data, 0x000000F0, write32_test # place 8'h11 into tx_data
|
||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||
#.8byte rx_data, 0x000000F0, read32_test # read rx_data
|
||||
|
||||
# =========== Test watermark interrupts ===========
|
||||
|
||||
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||
|
||||
SETUP_PLIC
|
||||
|
||||
.8byte fmt, 0x00000080, write32_test # reset fmt register
|
||||
.8byte tx_mark, 0x00000004, write32_test # set transmit watermark to 4
|
||||
#.8byte ie, 0x00000000, write32_test # enable transmit interrupt
|
||||
.8byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
|
||||
.8byte 0x0, 0x00000000, readmip_test
|
||||
.8byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||
.8byte ip, 0x00000000, read32_test # tx watermark interupt should be off
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
|
||||
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
|
||||
|
||||
.8byte tx_mark, 0x00000000, write32_test # set tx_mark to 0
|
||||
.8byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
|
||||
.8byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
|
||||
#.8byte ie, 0x0000002, write32_test # enable receive interrupts
|
||||
.8byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
|
||||
.8byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
|
||||
.8byte ip, 0x00000002, read32_test # recieve interrupt should be high
|
||||
.8byte 0x0, 0x00000000, readmip_test
|
||||
.8byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
|
||||
.8byte ip, 0x00000000, read32_test # receive interrupt should be low
|
||||
.8byte rx_data, 0x00000044, read32_test
|
||||
.8byte rx_data, 0x00000055, read32_test # clear rx fifo
|
||||
|
||||
|
||||
.8byte tx_mark, 0x00000004, write32_test # set transmit watermark to 4
|
||||
.8byte ie, 0x00000001, write32_test # enable transmit interrupt
|
||||
.8byte ip, 0x00000001, read32_test # tx watermark interupt should be pending
|
||||
.8byte 0x0, 0x00000800, readmip_test
|
||||
.8byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||
.8byte tx_mark, 0x00000001, write32_test
|
||||
.8byte 0x0, 0x00000000, claim_m_plic_interrupts
|
||||
.8byte ip, 0x00000000, read32_test # tx watermark interupt should be off
|
||||
.8byte 0x0, 0x00000000, readmip_test
|
||||
.8byte ie, 0x00000000, write32_test # disable tx intr
|
||||
.8byte 0x0, 0x00000003, spi_data_wait # wait for transmission to end
|
||||
|
||||
# test recieve watermark interrupt (triggers when entries in rx FIFO > rx watermark)
|
||||
|
||||
.8byte tx_mark, 0x00000000, write32_test
|
||||
.8byte rx_data, 0x00000022, read32_test # clear one entry from rx FIFO
|
||||
.8byte rx_mark, 0x00000003, write32_test # set recieve watermark to 3
|
||||
.8byte ie, 0x0000002, write32_test # enable receive interrupts
|
||||
.8byte ip, 0x00000000, read32_test # rx interrupts should be low (rx FIFO has 3 entries)
|
||||
.8byte 0x0, 0x00000000, readmip_test
|
||||
.8byte rx_mark, 0x00000002, write32_test # set recieve watermark to 2
|
||||
.8byte ip, 0x00000002, read32_test # recieve interrupt should be high
|
||||
.8byte 0x0, 0x00000800, readmip_test
|
||||
.8byte rx_data, 0x00000033, read32_test # clear one more entry from recieve FIFO (2 entries)
|
||||
.8byte 0x0, 0x00000000, claim_m_plic_interrupts
|
||||
.8byte ip, 0x00000000, read32_test # receive interrupt should be low
|
||||
.8byte 0x0, 0x00000000, readmip_test
|
||||
|
||||
.8byte 0x0, 0x0, terminate_test
|
Loading…
Reference in New Issue
Block a user