mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-06-28 09:36:01 -04:00
Merge branch 'main' into Zicclsm
This commit is contained in:
commit
b74bfbeefd
66 changed files with 2825 additions and 209 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit 873d16e748ad60023dcdda3926144957c096e31d
|
Subproject commit 197179fdc9dfeeca821e848f373c897a3fdae86c
|
|
@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Bus Interface width
|
||||||
localparam AHBW = 32'd64;
|
localparam AHBW = 32'd64;
|
||||||
|
@ -127,6 +130,7 @@ localparam AHBW = 32'd64;
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 0;
|
localparam GPIO_LOOPBACK_TEST = 0;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 0;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd0;
|
localparam UART_PRESCALE = 32'd0;
|
||||||
|
@ -136,6 +140,7 @@ localparam PLIC_NUM_SRC = 32'd53;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd20;
|
localparam PLIC_SDC_ID = 32'd20;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 1;
|
localparam BPRED_SUPPORTED = 1;
|
||||||
|
|
|
@ -136,10 +136,15 @@ localparam SDC_SUPPORTED = 1'b1;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Test modes
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 0;
|
localparam GPIO_LOOPBACK_TEST = 0;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 0;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd0;
|
localparam UART_PRESCALE = 32'd0;
|
||||||
|
@ -150,6 +155,7 @@ localparam PLIC_NUM_SRC = 32'd53;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd20;
|
localparam PLIC_SDC_ID = 32'd20;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 1;
|
localparam BPRED_SUPPORTED = 1;
|
||||||
|
|
|
@ -120,6 +120,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Bus Interface width
|
||||||
localparam AHBW = 32'd32;
|
localparam AHBW = 32'd32;
|
||||||
|
@ -128,6 +131,7 @@ localparam AHBW = 32'd32;
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 0;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
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_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 0;
|
localparam BPRED_SUPPORTED = 0;
|
||||||
|
|
|
@ -121,6 +121,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Bus Interface width
|
||||||
localparam AHBW = 32'd32;
|
localparam AHBW = 32'd32;
|
||||||
|
@ -129,6 +132,7 @@ localparam AHBW = 32'd32;
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
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_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 1;
|
localparam BPRED_SUPPORTED = 1;
|
||||||
|
|
|
@ -120,6 +120,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Bus Interface width
|
||||||
localparam AHBW = 32'd32;
|
localparam AHBW = 32'd32;
|
||||||
|
@ -128,6 +131,7 @@ localparam AHBW = 32'd32;
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
localparam UART_PRESCALE = 32'd1;
|
||||||
|
@ -138,6 +142,8 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
|
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 0;
|
localparam BPRED_SUPPORTED = 0;
|
||||||
|
|
|
@ -119,6 +119,9 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Bus Interface width
|
||||||
localparam AHBW = 32'd32;
|
localparam AHBW = 32'd32;
|
||||||
|
@ -127,6 +130,7 @@ localparam AHBW = 32'd32;
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
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_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 0;
|
localparam BPRED_SUPPORTED = 0;
|
||||||
|
|
|
@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Test modes
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
localparam UART_PRESCALE = 32'd1;
|
||||||
|
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 1;
|
localparam BPRED_SUPPORTED = 1;
|
||||||
|
|
|
@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Test modes
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
localparam UART_PRESCALE = 32'd1;
|
||||||
|
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 1;
|
localparam BPRED_SUPPORTED = 1;
|
||||||
|
|
|
@ -125,11 +125,15 @@ localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF;
|
||||||
localparam SDC_SUPPORTED = 1'b0;
|
localparam SDC_SUPPORTED = 1'b0;
|
||||||
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
localparam logic [63:0] SDC_BASE = 64'h00013000;
|
||||||
localparam logic [63:0] SDC_RANGE = 64'h0000007F;
|
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
|
// Test modes
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
localparam GPIO_LOOPBACK_TEST = 1;
|
localparam GPIO_LOOPBACK_TEST = 1;
|
||||||
|
localparam SPI_LOOPBACK_TEST = 1;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
localparam UART_PRESCALE = 32'd1;
|
localparam UART_PRESCALE = 32'd1;
|
||||||
|
@ -140,6 +144,7 @@ localparam PLIC_NUM_SRC = 32'd10;
|
||||||
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32);
|
||||||
localparam PLIC_GPIO_ID = 32'd3;
|
localparam PLIC_GPIO_ID = 32'd3;
|
||||||
localparam PLIC_UART_ID = 32'd10;
|
localparam PLIC_UART_ID = 32'd10;
|
||||||
|
localparam PLIC_SPI_ID = 32'd6;
|
||||||
localparam PLIC_SDC_ID = 32'd9;
|
localparam PLIC_SDC_ID = 32'd9;
|
||||||
|
|
||||||
localparam BPRED_SUPPORTED = 0;
|
localparam BPRED_SUPPORTED = 0;
|
||||||
|
|
|
@ -74,12 +74,17 @@ localparam cvw_t P = '{
|
||||||
SDC_SUPPORTED : SDC_SUPPORTED,
|
SDC_SUPPORTED : SDC_SUPPORTED,
|
||||||
SDC_BASE : SDC_BASE,
|
SDC_BASE : SDC_BASE,
|
||||||
SDC_RANGE : SDC_RANGE,
|
SDC_RANGE : SDC_RANGE,
|
||||||
|
SPI_SUPPORTED : SPI_SUPPORTED,
|
||||||
|
SPI_BASE : SPI_BASE,
|
||||||
|
SPI_RANGE : SPI_RANGE,
|
||||||
GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST,
|
GPIO_LOOPBACK_TEST : GPIO_LOOPBACK_TEST,
|
||||||
|
SPI_LOOPBACK_TEST : SPI_LOOPBACK_TEST,
|
||||||
UART_PRESCALE : UART_PRESCALE ,
|
UART_PRESCALE : UART_PRESCALE ,
|
||||||
PLIC_NUM_SRC : PLIC_NUM_SRC,
|
PLIC_NUM_SRC : PLIC_NUM_SRC,
|
||||||
PLIC_NUM_SRC_LT_32 : PLIC_NUM_SRC_LT_32,
|
PLIC_NUM_SRC_LT_32 : PLIC_NUM_SRC_LT_32,
|
||||||
PLIC_GPIO_ID : PLIC_GPIO_ID,
|
PLIC_GPIO_ID : PLIC_GPIO_ID,
|
||||||
PLIC_UART_ID : PLIC_UART_ID,
|
PLIC_UART_ID : PLIC_UART_ID,
|
||||||
|
PLIC_SPI_ID : PLIC_SPI_ID,
|
||||||
PLIC_SDC_ID : PLIC_SDC_ID,
|
PLIC_SDC_ID : PLIC_SDC_ID,
|
||||||
BPRED_SUPPORTED : BPRED_SUPPORTED,
|
BPRED_SUPPORTED : BPRED_SUPPORTED,
|
||||||
/* verilator lint_off ENUMVALUE */
|
/* verilator lint_off ENUMVALUE */
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
echo "Executing Wally setup.csh"
|
echo "Executing Wally setup.csh"
|
||||||
|
|
||||||
# Path to Wally repository
|
# Path to Wally repository
|
||||||
set WALLY = $PWD
|
setenv WALLY $PWD
|
||||||
echo '$WALLY set to ' ${WALLY}
|
echo '$WALLY set to ' ${WALLY}
|
||||||
|
|
||||||
# Extend alias which makes extending PATH much easier.
|
# Extend alias which makes extending PATH much easier.
|
||||||
|
|
|
@ -11,16 +11,21 @@
|
||||||
--override refRoot/cpu/tvec_align=64
|
--override refRoot/cpu/tvec_align=64
|
||||||
|
|
||||||
# bit manipulation
|
# bit manipulation
|
||||||
--override cpu/add_implicit_Extensions=B
|
--override cpu/add_Extensions=B
|
||||||
|
#--override cpu/add_implicit_Extensions=B
|
||||||
--override cpu/bitmanip_version=1.0.0
|
--override cpu/bitmanip_version=1.0.0
|
||||||
|
|
||||||
# More extensions
|
# More extensions
|
||||||
|
--override cpu/Zcb=T
|
||||||
|
|
||||||
|
# Cache block operations
|
||||||
--override cpu/Zicbom=T
|
--override cpu/Zicbom=T
|
||||||
--override cpu/Zicbop=T
|
--override cpu/Zicbop=T
|
||||||
--override cpu/Zicboz=T
|
--override cpu/Zicboz=T
|
||||||
--override cpu/Svpbmt=T
|
|
||||||
# 64 KiB continuous huge pages supported
|
# 64 KiB continuous huge pages supported
|
||||||
--override cpu/Svnapot_page_mask=1<<16
|
--override cpu/Svpbmt=T
|
||||||
|
--override cpu/Svnapot_page_mask=65536
|
||||||
|
|
||||||
|
|
||||||
# clarify
|
# clarify
|
||||||
|
@ -39,10 +44,14 @@
|
||||||
--override cpu/ignore_non_leaf_DAU=1
|
--override cpu/ignore_non_leaf_DAU=1
|
||||||
--override cpu/wfi_is_nop=T
|
--override cpu/wfi_is_nop=T
|
||||||
--override cpu/misa_Extensions_mask=0x0
|
--override cpu/misa_Extensions_mask=0x0
|
||||||
--override cpu/updatePTEA=T
|
|
||||||
--override cpu/updatePTED=T
|
|
||||||
--override cpu/Sstc=T
|
--override cpu/Sstc=T
|
||||||
|
|
||||||
|
# Enable SVADU hardware update of A/D bits when menvcfg.HADE=1
|
||||||
|
--override cpu/Svadu=T
|
||||||
|
--override cpu/updatePTEA=F
|
||||||
|
--override cpu/updatePTED=F
|
||||||
|
|
||||||
|
|
||||||
# THIS NEEDS FIXING to 16
|
# THIS NEEDS FIXING to 16
|
||||||
--override cpu/PMP_registers=16
|
--override cpu/PMP_registers=16
|
||||||
--override cpu/PMP_undefined=T
|
--override cpu/PMP_undefined=T
|
||||||
|
@ -68,7 +77,8 @@
|
||||||
--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw--A- 1248 " # CLINT
|
--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw--A- 1248 " # CLINT
|
||||||
--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw--A- --4- " # PLIC
|
--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw--A- --4- " # PLIC
|
||||||
--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw--A- 1--- " # UART0 error - 0x10000000 - 0x100000FF
|
--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw--A- 1--- " # UART0 error - 0x10000000 - 0x100000FF
|
||||||
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- " # GPIO error - 0x10006000 - 0x100060FF
|
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- " # GPIO error - 0x10069000 - 0x100600FF
|
||||||
|
--callcommand refRoot/cpu/setPMA -lo 0x0010040000 -hi 0x0010040FFF -attributes " rw--A- --4- " # SPI error - 0x10040000 - 0x10040FFF
|
||||||
--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM
|
--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM
|
||||||
|
|
||||||
# Enable the Imperas instruction coverage
|
# Enable the Imperas instruction coverage
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
vsim -do "do wally.do rv64gc wally64priv"
|
vsim -do "do wally.do rv64gc wally64periph"
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
vsim -c -do "do wally-batch.do rv64gc wally64priv"
|
vsim -c -do "do wally-batch.do rv64gc wally64periph"
|
||||||
|
|
10
sim/verilate
10
sim/verilate
|
@ -8,15 +8,9 @@ basepath=$(dirname $0)/..
|
||||||
#for config in rv32e rv64gc rv32gc rv32imc rv32i rv64i rv64fpquad; do
|
#for config in rv32e rv64gc rv32gc rv32imc rv32i rv64i rv64fpquad; do
|
||||||
for config in rv64gc; do
|
for config in rv64gc; do
|
||||||
echo "$config simulating..."
|
echo "$config simulating..."
|
||||||
if !($verilator --timescale "1ns/1ns" --timing --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/wally/cvw.sv $basepath/testbench/common/*.sv $basepath/testbench/testbench.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then
|
if !($verilator --timescale "1ns/1ns" --timing --exe --cc "$@" --top-module testbench "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/cvw.sv $basepath/testbench/testbench.sv $basepath/testbench/common/*.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then
|
||||||
echo "Exiting after $config lint due to errors or warnings"
|
echo "Exiting after $config lint due to errors or warnings"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo "All lints run with no errors or warnings"
|
echo "Verilation complete"
|
||||||
|
|
||||||
# --lint-only just runs lint rather than trying to compile and simulate
|
|
||||||
# -I points to the include directory where files such as `include config.vh are found
|
|
||||||
|
|
||||||
# For more exhaustive (and sometimes spurious) warnings, add --Wall to the Verilator command
|
|
||||||
# Unfortunately, this produces a bunch of UNUSED and UNDRIVEN signal warnings in blocks that are configured to not exist.
|
|
||||||
|
|
6
src/cache/cacheway.sv
vendored
6
src/cache/cacheway.sv
vendored
|
@ -126,7 +126,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||||
// Tag Array
|
// Tag Array
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
|
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(TAGLEN)) CacheTagMem(.clk, .ce(CacheEn),
|
||||||
.addr(CacheSet), .dout(ReadTag),
|
.addr(CacheSet), .dout(ReadTag),
|
||||||
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
.din(PAdr[PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN));
|
||||||
|
|
||||||
|
@ -148,12 +148,12 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
||||||
|
|
||||||
for(words = 0; words < NUMSRAM; words++) begin: word
|
for(words = 0; words < NUMSRAM; words++) begin: word
|
||||||
if (!READ_ONLY_CACHE) begin:wordram
|
if (!READ_ONLY_CACHE) begin:wordram
|
||||||
ram1p1rwbe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
||||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
.we(SelectedWriteWordEn), .bwe(FinalByteMask[SRAMLENINBYTES*(words+1)-1:SRAMLENINBYTES*words]));
|
||||||
end else begin:wordram // no byte-enable needed for i$.
|
end else begin:wordram // no byte-enable needed for i$.
|
||||||
ram1p1rwe #(.P(P), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
ram1p1rwe #(.USE_SRAM(P.USE_SRAM), .DEPTH(NUMLINES), .WIDTH(SRAMLEN)) CacheDataMem(.clk, .ce(CacheEn), .addr(CacheSet),
|
||||||
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.dout(ReadDataLine[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
.din(LineWriteData[SRAMLEN*(words+1)-1:SRAMLEN*words]),
|
||||||
.we(SelectedWriteWordEn));
|
.we(SelectedWriteWordEn));
|
||||||
|
|
|
@ -129,11 +129,15 @@ typedef struct packed {
|
||||||
logic SDC_SUPPORTED;
|
logic SDC_SUPPORTED;
|
||||||
logic [63:0] SDC_BASE;
|
logic [63:0] SDC_BASE;
|
||||||
logic [63:0] SDC_RANGE;
|
logic [63:0] SDC_RANGE;
|
||||||
|
logic SPI_SUPPORTED;
|
||||||
|
logic [63:0] SPI_BASE;
|
||||||
|
logic [63:0] SPI_RANGE;
|
||||||
|
|
||||||
// Test modes
|
// Test modes
|
||||||
|
|
||||||
// Tie GPIO outputs back to inputs
|
// Tie GPIO outputs back to inputs
|
||||||
logic GPIO_LOOPBACK_TEST;
|
logic GPIO_LOOPBACK_TEST;
|
||||||
|
logic SPI_LOOPBACK_TEST;
|
||||||
|
|
||||||
// Hardware configuration
|
// Hardware configuration
|
||||||
int UART_PRESCALE ;
|
int UART_PRESCALE ;
|
||||||
|
@ -143,6 +147,7 @@ typedef struct packed {
|
||||||
logic PLIC_NUM_SRC_LT_32;
|
logic PLIC_NUM_SRC_LT_32;
|
||||||
int PLIC_GPIO_ID;
|
int PLIC_GPIO_ID;
|
||||||
int PLIC_UART_ID;
|
int PLIC_UART_ID;
|
||||||
|
int PLIC_SPI_ID;
|
||||||
int PLIC_SDC_ID;
|
int PLIC_SDC_ID;
|
||||||
|
|
||||||
logic BPRED_SUPPORTED;
|
logic BPRED_SUPPORTED;
|
||||||
|
|
|
@ -68,7 +68,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||||
logic BZeroM; // Denominator is zero
|
logic BZeroM; // Denominator is zero
|
||||||
logic IntDivM; // Integer operation
|
logic IntDivM; // Integer operation
|
||||||
logic [P.DIVBLEN:0] nM, mM; // Shift amounts
|
logic [P.DIVBLEN:0] nM, mM; // Shift amounts
|
||||||
logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor
|
logic ALTBM, AsM, BsM, W64M; // Special handling for postprocessor
|
||||||
logic [P.XLEN-1:0] AM; // Original Numerator for postprocessor
|
logic [P.XLEN-1:0] AM; // Original Numerator for postprocessor
|
||||||
logic ISpecialCaseE; // Integer div/remainder special cases
|
logic ISpecialCaseE; // Integer div/remainder special cases
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||||
// Int-specific
|
// Int-specific
|
||||||
.ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
|
.ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
|
||||||
.BZeroM, .nM, .mM, .AM,
|
.BZeroM, .nM, .mM, .AM,
|
||||||
.IntDivM, .W64M, .NegQuotM, .ALTBM, .AsM);
|
.IntDivM, .W64M, .ALTBM, .AsM, .BsM);
|
||||||
|
|
||||||
fdivsqrtfsm #(P) fdivsqrtfsm( // FSM
|
fdivsqrtfsm #(P) fdivsqrtfsm( // FSM
|
||||||
.clk, .reset, .XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE,
|
.clk, .reset, .XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE,
|
||||||
|
@ -96,6 +96,6 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||||
.SqrtE, .Firstun, .SqrtM, .SpecialCaseM,
|
.SqrtE, .Firstun, .SqrtM, .SpecialCaseM,
|
||||||
.QmM, .WZeroE, .DivStickyM,
|
.QmM, .WZeroE, .DivStickyM,
|
||||||
// Int-specific
|
// Int-specific
|
||||||
.nM, .mM, .ALTBM, .AsM, .BZeroM, .NegQuotM, .W64M, .RemOpM(Funct3M[1]), .AM,
|
.nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM,
|
||||||
.FIntDivResultM);
|
.FIntDivResultM);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -65,7 +65,8 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
|
if (SqrtE) fbits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1; is it related to DIVCOPIES logic below?
|
||||||
|
// if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
|
||||||
else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
|
else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
|
||||||
if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
|
if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
|
||||||
else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
|
else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
|
||||||
|
|
|
@ -34,9 +34,9 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.DIVb:0] FirstU, FirstUM,
|
input logic [P.DIVb:0] FirstU, FirstUM,
|
||||||
input logic [P.DIVb+1:0] FirstC,
|
input logic [P.DIVb+1:0] FirstC,
|
||||||
input logic SqrtE,
|
input logic SqrtE,
|
||||||
input logic Firstun, SqrtM, SpecialCaseM, NegQuotM,
|
input logic Firstun, SqrtM, SpecialCaseM,
|
||||||
input logic [P.XLEN-1:0] AM,
|
input logic [P.XLEN-1:0] AM,
|
||||||
input logic RemOpM, ALTBM, BZeroM, AsM, W64M,
|
input logic RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
|
||||||
input logic [P.DIVBLEN:0] nM, mM,
|
input logic [P.DIVBLEN:0] nM, mM,
|
||||||
output logic [P.DIVb:0] QmM,
|
output logic [P.DIVb:0] QmM,
|
||||||
output logic WZeroE,
|
output logic WZeroE,
|
||||||
|
@ -49,6 +49,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
|
||||||
logic NegStickyM;
|
logic NegStickyM;
|
||||||
logic weq0E, WZeroM;
|
logic weq0E, WZeroM;
|
||||||
logic [P.XLEN-1:0] IntDivResultM;
|
logic [P.XLEN-1:0] IntDivResultM;
|
||||||
|
logic NegQuotM; // Integer quotient is negative
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Execute Stage: Detect early termination for an exact result
|
// Execute Stage: Detect early termination for an exact result
|
||||||
|
@ -103,6 +104,7 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
|
||||||
assign UnsignedQuotM = {3'b000, PreQmM};
|
assign UnsignedQuotM = {3'b000, PreQmM};
|
||||||
|
|
||||||
// Integer remainder: sticky and sign correction muxes
|
// Integer remainder: sticky and sign correction muxes
|
||||||
|
assign NegQuotM = AsM ^ BsM; // Integer Quotient is negative
|
||||||
mux2 #(P.DIVb+4) normremdmux(W, W+D, NegStickyM, NormRemDM);
|
mux2 #(P.DIVb+4) normremdmux(W, W+D, NegStickyM, NormRemDM);
|
||||||
mux2 #(P.DIVb+4) normremsmux(NormRemDM, -NormRemDM, AsM, NormRemM);
|
mux2 #(P.DIVb+4) normremsmux(NormRemDM, -NormRemDM, AsM, NormRemM);
|
||||||
mux2 #(P.DIVb+4) quotresmux(UnsignedQuotM, -UnsignedQuotM, NegQuotM, NormQuotM);
|
mux2 #(P.DIVb+4) quotresmux(UnsignedQuotM, -UnsignedQuotM, NegQuotM, NormQuotM);
|
||||||
|
|
|
@ -43,8 +43,8 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||||
output logic ISpecialCaseE,
|
output logic ISpecialCaseE,
|
||||||
output logic [P.DURLEN-1:0] CyclesE,
|
output logic [P.DURLEN-1:0] CyclesE,
|
||||||
output logic [P.DIVBLEN:0] nM, mM,
|
output logic [P.DIVBLEN:0] nM, mM,
|
||||||
output logic NegQuotM, ALTBM, IntDivM, W64M,
|
output logic ALTBM, IntDivM, W64M,
|
||||||
output logic AsM, BZeroM,
|
output logic AsM, BsM, BZeroM,
|
||||||
output logic [P.XLEN-1:0] AM
|
output logic [P.XLEN-1:0] AM
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -57,7 +57,6 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||||
logic NumerZeroE; // Numerator is zero (X or A)
|
logic NumerZeroE; // Numerator is zero (X or A)
|
||||||
logic AZeroE, BZeroE; // A or B is Zero for integer division
|
logic AZeroE, BZeroE; // A or B is Zero for integer division
|
||||||
logic SignedDivE; // signed division
|
logic SignedDivE; // signed division
|
||||||
logic NegQuotE; // Integer quotient is negative
|
|
||||||
logic AsE, BsE; // Signs of integer inputs
|
logic AsE, BsE; // Signs of integer inputs
|
||||||
logic [P.XLEN-1:0] AE; // input A after W64 adjustment
|
logic [P.XLEN-1:0] AE; // input A after W64 adjustment
|
||||||
logic ALTBE;
|
logic ALTBE;
|
||||||
|
@ -84,7 +83,6 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||||
assign BZeroE = ~(|BE);
|
assign BZeroE = ~(|BE);
|
||||||
assign AsE = AE[P.XLEN-1] & SignedDivE;
|
assign AsE = AE[P.XLEN-1] & SignedDivE;
|
||||||
assign BsE = BE[P.XLEN-1] & SignedDivE;
|
assign BsE = BE[P.XLEN-1] & SignedDivE;
|
||||||
assign NegQuotE = AsE ^ BsE; // Integer Quotient is negative
|
|
||||||
|
|
||||||
// Force integer inputs to be postiive
|
// Force integer inputs to be postiive
|
||||||
mux2 #(P.XLEN) posamux(AE, -AE, AsE, PosA);
|
mux2 #(P.XLEN) posamux(AE, -AE, AsE, PosA);
|
||||||
|
@ -192,9 +190,9 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||||
// pipeline registers
|
// pipeline registers
|
||||||
flopen #(1) mdureg(clk, IFDivStartE, IntDivE, IntDivM);
|
flopen #(1) mdureg(clk, IFDivStartE, IntDivE, IntDivM);
|
||||||
flopen #(1) altbreg(clk, IFDivStartE, ALTBE, ALTBM);
|
flopen #(1) altbreg(clk, IFDivStartE, ALTBE, ALTBM);
|
||||||
flopen #(1) negquotreg(clk, IFDivStartE, NegQuotE, NegQuotM);
|
|
||||||
flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM);
|
flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM);
|
||||||
flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM);
|
flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM);
|
||||||
|
flopen #(1) bsignreg(clk, IFDivStartE, BsE, BsM);
|
||||||
flopen #(P.DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM);
|
flopen #(P.DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM);
|
||||||
flopen #(P.DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM);
|
flopen #(P.DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM);
|
||||||
flopen #(P.XLEN) srcareg(clk, IFDivStartE, AE, AM);
|
flopen #(P.XLEN) srcareg(clk, IFDivStartE, AE, AM);
|
||||||
|
|
|
@ -32,8 +32,7 @@
|
||||||
|
|
||||||
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
||||||
|
|
||||||
module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=44,
|
module ram1p1rwbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44, PRELOAD_ENABLED=0) (
|
||||||
parameter PRELOAD_ENABLED=0) (
|
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic ce,
|
input logic ce,
|
||||||
input logic [$clog2(DEPTH)-1:0] addr,
|
input logic [$clog2(DEPTH)-1:0] addr,
|
||||||
|
@ -48,7 +47,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
// TRUE SRAM macro
|
// TRUE SRAM macro
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
|
if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
|
||||||
genvar index;
|
genvar index;
|
||||||
// 64 x 128-bit SRAM
|
// 64 x 128-bit SRAM
|
||||||
logic [WIDTH-1:0] BitWriteMask;
|
logic [WIDTH-1:0] BitWriteMask;
|
||||||
|
@ -58,7 +57,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
|
||||||
.A(addr), .D(din),
|
.A(addr), .D(din),
|
||||||
.BWEB(~BitWriteMask), .Q(dout));
|
.BWEB(~BitWriteMask), .Q(dout));
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
|
end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
|
||||||
genvar index;
|
genvar index;
|
||||||
// 64 x 44-bit SRAM
|
// 64 x 44-bit SRAM
|
||||||
logic [WIDTH-1:0] BitWriteMask;
|
logic [WIDTH-1:0] BitWriteMask;
|
||||||
|
@ -68,7 +67,7 @@ module ram1p1rwbe import cvw::*; #(parameter cvw_t P, parameter DEPTH=64, WIDTH=
|
||||||
.A(addr), .D(din),
|
.A(addr), .D(din),
|
||||||
.BWEB(~BitWriteMask), .Q(dout));
|
.BWEB(~BitWriteMask), .Q(dout));
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
|
end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
|
||||||
genvar index;
|
genvar index;
|
||||||
// 64 x 22-bit SRAM
|
// 64 x 22-bit SRAM
|
||||||
logic [WIDTH-1:0] BitWriteMask;
|
logic [WIDTH-1:0] BitWriteMask;
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
|
|
||||||
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
||||||
|
|
||||||
module ram1p1rwe import cvw::* ; #(parameter cvw_t P,
|
module ram1p1rwe import cvw::* ; #(parameter USE_SRAM=0, DEPTH=64, WIDTH=44) (
|
||||||
parameter DEPTH=64, WIDTH=44) (
|
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic ce,
|
input logic ce,
|
||||||
input logic [$clog2(DEPTH)-1:0] addr,
|
input logic [$clog2(DEPTH)-1:0] addr,
|
||||||
|
@ -45,19 +44,19 @@ module ram1p1rwe import cvw::* ; #(parameter cvw_t P,
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
// TRUE SRAM macro
|
// TRUE SRAM macro
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
if ((P.USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
|
if ((USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray
|
||||||
// 64 x 128-bit SRAM
|
// 64 x 128-bit SRAM
|
||||||
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
|
ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||||
.A(addr), .D(din),
|
.A(addr), .D(din),
|
||||||
.BWEB('0), .Q(dout));
|
.BWEB('0), .Q(dout));
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
|
end else if ((USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag
|
||||||
// 64 x 44-bit SRAM
|
// 64 x 44-bit SRAM
|
||||||
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
|
ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||||
.A(addr), .D(din),
|
.A(addr), .D(din),
|
||||||
.BWEB('0), .Q(dout));
|
.BWEB('0), .Q(dout));
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
|
end else if ((USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag
|
||||||
// 64 x 22-bit SRAM
|
// 64 x 22-bit SRAM
|
||||||
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
|
ram1p1rwbe_64x22 sram1 (.CLK(clk), .CEB(~ce), .WEB(~we),
|
||||||
.A(addr), .D(din),
|
.A(addr), .D(din),
|
||||||
|
|
|
@ -31,8 +31,7 @@
|
||||||
|
|
||||||
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
// WIDTH is number of bits in one "word" of the memory, DEPTH is number of such words
|
||||||
|
|
||||||
module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
|
module ram2p1r1wbe import cvw::*; #(parameter USE_SRAM=0, DEPTH=1024, WIDTH=68) (
|
||||||
parameter DEPTH=1024, WIDTH=68) (
|
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic ce1, ce2,
|
input logic ce1, ce2,
|
||||||
input logic [$clog2(DEPTH)-1:0] ra1,
|
input logic [$clog2(DEPTH)-1:0] ra1,
|
||||||
|
@ -51,7 +50,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
|
||||||
// TRUE Smem macro
|
// TRUE Smem macro
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
if ((P.USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin
|
if ((USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin
|
||||||
|
|
||||||
ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
|
ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk),
|
||||||
.CEBA(~ce1), .CEBB(~ce2),
|
.CEBA(~ce1), .CEBB(~ce2),
|
||||||
|
@ -63,7 +62,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
|
||||||
.QA(rd1),
|
.QA(rd1),
|
||||||
.QB());
|
.QB());
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin
|
end else if ((USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin
|
||||||
|
|
||||||
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
|
ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk),
|
||||||
.CEBA(~ce1), .CEBB(~ce2),
|
.CEBA(~ce1), .CEBB(~ce2),
|
||||||
|
@ -75,7 +74,7 @@ module ram2p1r1wbe import cvw::*; #(parameter cvw_t P,
|
||||||
.QA(rd1),
|
.QA(rd1),
|
||||||
.QB());
|
.QB());
|
||||||
|
|
||||||
end else if ((P.USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin
|
end else if ((USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin
|
||||||
|
|
||||||
logic [SRAMWIDTH-1:0] SRAMReadData;
|
logic [SRAMWIDTH-1:0] SRAMReadData;
|
||||||
logic [SRAMWIDTH-1:0] SRAMWriteData;
|
logic [SRAMWIDTH-1:0] SRAMWriteData;
|
||||||
|
|
|
@ -25,9 +25,7 @@
|
||||||
|
|
||||||
// This model actually works correctly with vivado.
|
// This model actually works correctly with vivado.
|
||||||
|
|
||||||
module rom1p1r #(parameter ADDR_WIDTH = 8,
|
module rom1p1r #(parameter ADDR_WIDTH = 8, DATA_WIDTH = 32, PRELOAD_ENABLED = 0)
|
||||||
parameter DATA_WIDTH = 32,
|
|
||||||
parameter PRELOAD_ENABLED = 0)
|
|
||||||
(input logic clk,
|
(input logic clk,
|
||||||
input logic ce,
|
input logic ce,
|
||||||
input logic [ADDR_WIDTH-1:0] addr,
|
input logic [ADDR_WIDTH-1:0] addr,
|
||||||
|
|
|
@ -92,7 +92,7 @@ module btb import cvw::*; #(parameter cvw_t P,
|
||||||
|
|
||||||
|
|
||||||
// An optimization may be using a PC relative address.
|
// An optimization may be using a PC relative address.
|
||||||
ram2p1r1wbe #(P, 2**Depth, P.XLEN+4) memory(
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**Depth), .WIDTH(P.XLEN+4)) memory(
|
||||||
.clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF),
|
.clk, .ce1(~StallF | reset), .ra1(PCNextFIndex), .rd1(TableBTBPredF),
|
||||||
.ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1));
|
.ce2(~StallW & ~FlushW), .wa2(PCMIndex), .wd2({InstrClassM, IEUAdrM}), .we2(BTBWrongM), .bwe2('1));
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ module gshare import cvw::*; #(parameter cvw_t P,
|
||||||
|
|
||||||
assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
|
assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexNextF),
|
.ra1(IndexNextF),
|
||||||
.rd1(TableBPDirPredF),
|
.rd1(TableBPDirPredF),
|
||||||
|
|
|
@ -58,7 +58,7 @@ module gsharebasic import cvw::*; #(parameter cvw_t P,
|
||||||
assign IndexM = GHRM;
|
assign IndexM = GHRM;
|
||||||
end
|
end
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexNextF),
|
.ra1(IndexNextF),
|
||||||
.rd1(BPDirPredF),
|
.rd1(BPDirPredF),
|
||||||
|
|
|
@ -59,7 +59,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
|
||||||
//assign IndexNextF = LHR;
|
//assign IndexNextF = LHR;
|
||||||
assign IndexM = LHRW;
|
assign IndexM = LHRW;
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallD), .ce2(~StallW & ~FlushW),
|
.ce1(~StallD), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(LHRF),
|
.ra1(LHRF),
|
||||||
.rd1(BPDirPredD),
|
.rd1(BPDirPredD),
|
||||||
|
@ -92,7 +92,7 @@ module localaheadbp import cvw::*; #(parameter cvw_t P,
|
||||||
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
|
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
|
||||||
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
|
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexLHRNextF),
|
.ra1(IndexLHRNextF),
|
||||||
.rd1(LHRF),
|
.rd1(LHRF),
|
||||||
|
|
|
@ -56,7 +56,7 @@ module localbpbasic import cvw::*; #(parameter cvw_t P,
|
||||||
assign IndexNextF = LHR;
|
assign IndexNextF = LHR;
|
||||||
assign IndexM = LHRM;
|
assign IndexM = LHRM;
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexNextF),
|
.ra1(IndexNextF),
|
||||||
.rd1(BPDirPredF),
|
.rd1(BPDirPredF),
|
||||||
|
|
|
@ -58,7 +58,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
|
||||||
logic SpeculativeFlushedF;
|
logic SpeculativeFlushedF;
|
||||||
|
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallD), .ce2(~StallW & ~FlushW),
|
.ce1(~StallD), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(LHRF),
|
.ra1(LHRF),
|
||||||
.rd1(BPDirPredD),
|
.rd1(BPDirPredD),
|
||||||
|
@ -89,7 +89,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
|
||||||
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
|
assign IndexLHRM = {PCW[m+1] ^ PCW[1], PCW[m:2]};
|
||||||
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
|
assign IndexLHRNextF = {PCNextF[m+1] ^ PCNextF[1], PCNextF[m:2]};
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**m, k) BHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) BHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexLHRNextF),
|
.ra1(IndexLHRNextF),
|
||||||
.rd1(LHRCommittedF),
|
.rd1(LHRCommittedF),
|
||||||
|
@ -101,7 +101,7 @@ module localrepairbp import cvw::*; #(parameter cvw_t P,
|
||||||
assign IndexLHRD = {PCE[m+1] ^ PCE[1], PCE[m:2]};
|
assign IndexLHRD = {PCE[m+1] ^ PCE[1], PCE[m:2]};
|
||||||
assign LHRNextE = BranchD ? {BPDirPredD[1], LHRE[k-1:1]} : LHRE;
|
assign LHRNextE = BranchD ? {BPDirPredD[1], LHRE[k-1:1]} : LHRE;
|
||||||
// *** replace with a small CAM
|
// *** replace with a small CAM
|
||||||
ram2p1r1wbe #(P, 2**m, k) SHB(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**m), .WIDTH(k)) SHB(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallE & ~FlushE),
|
.ce1(~StallF), .ce2(~StallE & ~FlushE),
|
||||||
.ra1(IndexLHRNextF),
|
.ra1(IndexLHRNextF),
|
||||||
.rd1(LHRSpeculativeF),
|
.rd1(LHRSpeculativeF),
|
||||||
|
|
|
@ -53,7 +53,7 @@ module twoBitPredictor import cvw::*; #(parameter cvw_t P, parameter XLEN,
|
||||||
assign IndexM = {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
assign IndexM = {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
||||||
|
|
||||||
|
|
||||||
ram2p1r1wbe #(P, 2**k, 2) PHT(.clk(clk),
|
ram2p1r1wbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(2**k), .WIDTH(2)) PHT(.clk(clk),
|
||||||
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
.ce1(~StallF), .ce2(~StallW & ~FlushW),
|
||||||
.ra1(IndexNextF),
|
.ra1(IndexNextF),
|
||||||
.rd1(BPDirPredF),
|
.rd1(BPDirPredF),
|
||||||
|
|
|
@ -114,10 +114,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||||
logic CompressedF; // The fetched instruction is compressed
|
logic CompressedF, CompressedE; // The fetched instruction is compressed
|
||||||
logic CompressedD; // The decoded instruction is compressed
|
|
||||||
logic CompressedE; // The execution instruction is compressed
|
|
||||||
logic CompressedM; // The execution instruction is compressed
|
|
||||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||||
|
@ -389,31 +386,40 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||||
assign BranchMisalignedFaultE = (IEUAdrE[1] & ~P.COMPRESSED_SUPPORTED) & PCSrcE;
|
assign BranchMisalignedFaultE = (IEUAdrE[1] & ~P.COMPRESSED_SUPPORTED) & PCSrcE;
|
||||||
flopenr #(1) InstrMisalignedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM);
|
flopenr #(1) InstrMisalignedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM);
|
||||||
|
|
||||||
// Instruction and PC pipeline registers
|
// Instruction and PC pipeline registers flush to NOP, not zero
|
||||||
// Cannot use flopenrc for Instr(E/M) as it resets to NOP not 0.
|
|
||||||
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD);
|
||||||
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
|
||||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE);
|
||||||
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE);
|
||||||
|
|
||||||
// InstrM is only needed with CSRs or atomic operations
|
// InstrM is only needed with CSRs or atomic operations
|
||||||
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED)
|
if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin
|
||||||
|
mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE);
|
||||||
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM);
|
||||||
else assign InstrM = 0;
|
end else assign InstrM = 0;
|
||||||
// PCM is only needed with CSRs or branch prediction
|
// PCM is only needed with CSRs or branch prediction
|
||||||
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
|
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED)
|
||||||
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM);
|
||||||
else assign PCM = 0;
|
else assign PCM = 0;
|
||||||
|
|
||||||
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD);
|
// If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
|
||||||
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE);
|
if (P.COMPRESSED_SUPPORTED) begin
|
||||||
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion
|
logic CompressedD; // instruction is compressed
|
||||||
|
flopenrc #(1) CompressedDReg(clk, reset, FlushD, ~StallD, CompressedF, CompressedD);
|
||||||
|
flopenrc #(1) CompressedEReg(clk, reset, FlushE, ~StallE, CompressedD, CompressedE);
|
||||||
|
assign PCLinkE = PCE + (CompressedE ? 'd2 : 'd4); // 'd4 means 4 but stops Design Compiler complaining about signed to unsigned conversion
|
||||||
|
end else begin
|
||||||
|
assign CompressedE = 0;
|
||||||
|
assign PCLinkE = PCE + 'd4;
|
||||||
|
end
|
||||||
|
|
||||||
// pipeline original compressed instruction in case it is needed for MTVAL on an illegal instruction exception
|
// pipeline original compressed instruction in case it is needed for MTVAL on an illegal instruction exception
|
||||||
if (P.ZICSR_SUPPORTED) begin
|
if (P.ZICSR_SUPPORTED & P.COMPRESSED_SUPPORTED | 1) begin
|
||||||
|
logic CompressedM; // instruction is compressed
|
||||||
flopenrc #(16) InstrRawEReg(clk, reset, FlushE, ~StallE, InstrRawD[15:0], InstrRawE);
|
flopenrc #(16) InstrRawEReg(clk, reset, FlushE, ~StallE, InstrRawD[15:0], InstrRawE);
|
||||||
flopenrc #(16) InstrRawMReg(clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
|
flopenrc #(16) InstrRawMReg(clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
|
||||||
flopenrc #(1) CompressedMReg(clk, reset, FlushM, ~StallM, CompressedE, CompressedM);
|
flopenrc #(1) CompressedMReg(clk, reset, FlushM, ~StallM, CompressedE, CompressedM);
|
||||||
mux2 #(32) InstrOrigMux(InstrM, {16'b0, InstrRawM}, CompressedM, InstrOrigM);
|
mux2 #(32) InstrOrigMux(InstrM, {16'b0, InstrRawM}, CompressedM, InstrOrigM);
|
||||||
end else assign InstrOrigM = 0;
|
end else
|
||||||
|
assign InstrOrigM = InstrM;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -49,6 +49,6 @@ module dtim import cvw::*; #(parameter cvw_t P) (
|
||||||
|
|
||||||
assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap.
|
assign we = MemRWM[0] & ~FlushW; // have to ignore write if Trap.
|
||||||
|
|
||||||
ram1p1rwbe #(.P(P), .DEPTH(DEPTH), .WIDTH(P.LLEN))
|
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(DEPTH), .WIDTH(P.LLEN))
|
||||||
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
ram(.clk, .ce, .we, .bwe(ByteMaskM), .addr(DTIMAdr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(ReadDataWordM), .din(WriteDataM));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -32,23 +32,24 @@ module adrdecs import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
input logic [P.PA_BITS-1:0] PhysicalAddress,
|
||||||
input logic AccessRW, AccessRX, AccessRWX,
|
input logic AccessRW, AccessRX, AccessRWX,
|
||||||
input logic [1:0] Size,
|
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);
|
localparam logic [3:0] SUPPORTED_SIZE = (P.LLEN == 32 ? 4'b0111 : 4'b1111);
|
||||||
// Determine which region of physical memory (if any) is being accessed
|
// 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) 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[9]);
|
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[8]);
|
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[7]);
|
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[6]);
|
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[5]);
|
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[4]);
|
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[3]);
|
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[2]);
|
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, SelRegions[1]);
|
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
|
endmodule
|
||||||
|
|
||||||
// verilator lint_on UNOPTFLAT
|
// verilator lint_on UNOPTFLAT
|
||||||
|
|
|
@ -44,7 +44,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||||
|
|
||||||
logic PMAAccessFault;
|
logic PMAAccessFault;
|
||||||
logic AccessRW, AccessRWX, AccessRX;
|
logic AccessRW, AccessRWX, AccessRX;
|
||||||
logic [10:0] SelRegions;
|
logic [11:0] SelRegions;
|
||||||
logic AtomicAllowed;
|
logic AtomicAllowed;
|
||||||
logic CacheableRegion, IdempotentRegion;
|
logic CacheableRegion, IdempotentRegion;
|
||||||
|
|
||||||
|
@ -57,18 +57,18 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
||||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions);
|
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
|
// 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;
|
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0;
|
||||||
|
|
||||||
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
|
// 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
|
// 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 IdempotentRegion = SelRegions[11] | SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7]; // exclusion-tag: unused-idempotent
|
||||||
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01);
|
assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01);
|
||||||
|
|
||||||
// Atomic operations are only allowed on RAM
|
// 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]; // exclusion-tag: unused-idempotent
|
||||||
// Check if tightly integrated memories are selected
|
// Check if tightly integrated memories are selected
|
||||||
assign SelTIM = SelRegions[10] | SelRegions[9]; // exclusion-tag: unused-tim
|
assign SelTIM = SelRegions[11] | SelRegions[10]; // exclusion-tag: unused-idempotent
|
||||||
|
|
||||||
// Detect access faults
|
// Detect access faults
|
||||||
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
assign PMAAccessFault = (SelRegions[0]) & AccessRWX | AtomicAccessM & ~AtomicAllowed;
|
||||||
|
|
|
@ -49,7 +49,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic PENABLE,
|
input logic PENABLE,
|
||||||
output logic [P.XLEN-1:0] PRDATA,
|
output logic [P.XLEN-1:0] PRDATA,
|
||||||
output logic PREADY,
|
output logic PREADY,
|
||||||
input logic UARTIntr,GPIOIntr,SDCIntr,
|
input logic UARTIntr,GPIOIntr, SPIIntr, SDCIntr,
|
||||||
output logic MExtInt, SExtInt
|
output logic MExtInt, SExtInt
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||||
requests = {P.PLIC_NUM_SRC{1'b0}};
|
requests = {P.PLIC_NUM_SRC{1'b0}};
|
||||||
if(P.PLIC_GPIO_ID != 0) requests[P.PLIC_GPIO_ID] = GPIOIntr;
|
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_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;
|
if(P.PLIC_SDC_ID !=0) requests[P.PLIC_SDC_ID] = SDCIntr;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
||||||
mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
|
mux2 #(P.PA_BITS) adrmux(HADDR, HADDRD, memwriteD | ~HREADY, RamAddr);
|
||||||
|
|
||||||
// single-ported RAM
|
// single-ported RAM
|
||||||
ram1p1rwbe #(.P(P), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1),
|
ram1p1rwbe #(.USE_SRAM(P.USE_SRAM), .DEPTH(RANGE/8), .WIDTH(P.XLEN), .PRELOAD_ENABLED(P.FPGA)) memory(.clk(HCLK), .ce(1'b1),
|
||||||
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
|
.addr(RamAddr[ADDR_WIDTH+OFFSET-1:OFFSET]), .we(memwriteD), .din(HWDATA), .bwe(HWSTRB), .dout(HREADRam));
|
||||||
|
|
||||||
// use this to add arbitrary latency to ram. Helps test AHB controller correctness
|
// use this to add arbitrary latency to ram. Helps test AHB controller correctness
|
||||||
|
|
500
src/uncore/spi_apb.sv
Normal file
500
src/uncore/spi_apb.sv
Normal file
|
@ -0,0 +1,500 @@
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Attempt to move from >= comparisons by initializing in FSM differently
|
||||||
|
// Parameterize SynchFIFO
|
||||||
|
// look at ReadIncrement/WriteIncrement delay necessity
|
||||||
|
|
||||||
|
/*
|
||||||
|
SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers.
|
||||||
|
The FIFOs are connected to WALLY by an apb control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing
|
||||||
|
to the transmit FIFO and reading from the receive FIFO. The transmissions themselves are then controlled by a finite state machine. The SPI module uses 4 tristate pins for SPI input/output,
|
||||||
|
along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal to WALLY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 SPIOut,
|
||||||
|
input logic SPIIn,
|
||||||
|
output logic [3:0] SPICS,
|
||||||
|
output logic SPIIntr
|
||||||
|
);
|
||||||
|
|
||||||
|
//SPI control registers. Refer to SiFive FU540-C000 manual
|
||||||
|
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 [4:0] Format;
|
||||||
|
logic [7:0] ReceiveData;
|
||||||
|
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 TransmitInactive; //High when there is no transmission, used as hardware interlock signal
|
||||||
|
|
||||||
|
//FIFO FSM signals
|
||||||
|
//Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
|
||||||
|
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
||||||
|
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
||||||
|
logic TransmitFIFOReadIncrement;
|
||||||
|
logic TransmitFIFOWriteIncrement;
|
||||||
|
logic ReceiveFIFOReadIncrement;
|
||||||
|
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
||||||
|
logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData;
|
||||||
|
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel;
|
||||||
|
logic [7:0] ReceiveShiftRegEndian; //reverses ReceiveShiftReg if Format[2] set (little endian transmission)
|
||||||
|
|
||||||
|
//Transmission signals
|
||||||
|
logic sck;
|
||||||
|
logic [11:0] DivCounter; //counter for sck
|
||||||
|
logic SCLKenable; //flip flop enable high every sclk edge
|
||||||
|
|
||||||
|
//Delay signals
|
||||||
|
logic [8:0] ImplicitDelay1; //Adds implicit delay to cs-sck delay counter based on phase
|
||||||
|
logic [8:0] ImplicitDelay2; //Adds implicit delay to sck-cs delay counter based on phase
|
||||||
|
logic [8:0] CS_SCKCount; //Counter for cs-sck delay
|
||||||
|
logic [8:0] SCK_CSCount; //Counter for sck-cs delay
|
||||||
|
logic [8:0] InterCSCount; //Counter for inter cs delay
|
||||||
|
logic [8:0] InterXFRCount; //Counter for inter xfr delay
|
||||||
|
logic CS_SCKCompare; //Boolean comparison signal, high when CS_SCKCount >= cs-sck delay
|
||||||
|
logic SCK_CSCompare; //Boolean comparison signal, high when SCK_CSCount >= sck-cs delay
|
||||||
|
logic InterCSCompare; //Boolean comparison signal, high when InterCSCount >= inter cs delay
|
||||||
|
logic InterXFRCompare; //Boolean comparison signal, high when InterXFRCount >= inter xfr delay
|
||||||
|
logic ZeroDelayHoldMode; //High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
|
||||||
|
|
||||||
|
//Frame counting signals
|
||||||
|
logic [3:0] FrameCount; //Counter for number of frames in transmission
|
||||||
|
logic FrameCompare; //Boolean comparison signal, high when FrameCount = Format[7:4]
|
||||||
|
logic [3:0] ReceivePenultimateFrame; //Frame number - 1
|
||||||
|
logic [3:0] ReceivePenultimateFrameCount; //Counter
|
||||||
|
logic ReceivePenultimateFrameBoolean; //High when penultimate frame in transmission has been reached
|
||||||
|
|
||||||
|
//State fsm signals
|
||||||
|
logic Active; //High when state is either Active1 or Active0 (during transmission)
|
||||||
|
logic Active0; //High when state is Active0
|
||||||
|
|
||||||
|
//Shift reg signals
|
||||||
|
logic ShiftEdge; //Determines which edge of sck to shift from TransmitShiftReg
|
||||||
|
logic [7:0] TransmitShiftReg; //Transmit shift register
|
||||||
|
logic [7:0] ReceiveShiftReg; //Receive shift register
|
||||||
|
logic SampleEdge; //Determines which edge of sck to sample from ReceiveShiftReg
|
||||||
|
logic [7:0] TransmitDataEndian; //Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
|
||||||
|
logic TransmitShiftRegLoad; //Determines when to load TransmitShiftReg
|
||||||
|
logic ReceiveShiftFull; //High when receive shift register is full
|
||||||
|
logic TransmitShiftEmpty; //High when transmit shift register is empty
|
||||||
|
logic ShiftIn; //Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST)
|
||||||
|
logic [3:0] LeftShiftAmount; //Determines left shift amount to left-align data when little endian
|
||||||
|
logic [7:0] ASR; //AlignedReceiveShiftReg
|
||||||
|
|
||||||
|
//CS signals
|
||||||
|
logic [3:0] ChipSelectAuto; //Assigns ChipSelect value to selected CS signal based on CS ID
|
||||||
|
logic [3:0] ChipSelectInternal; //Defines what each ChipSelect signal should be based on transmission status and ChipSelectDef
|
||||||
|
logic DelayMode; //Determines where to place implicit half cycle delay based on sck phase for CS assertion
|
||||||
|
|
||||||
|
//Miscellaneous signals delayed/early by 1 PCLK cycle
|
||||||
|
logic ReceiveShiftFullDelay; //Delays ReceiveShiftFull signal by 1 PCLK cycle
|
||||||
|
logic TransmitFIFOWriteIncrementDelay; //TransmitFIFOWriteIncrement delayed by 1 PCLK cycle
|
||||||
|
logic ReceiveShiftFullDelayPCLK; //ReceiveShiftFull delayed by 1 PCLK cycle
|
||||||
|
logic TransmitFIFOReadEmptyDelay;
|
||||||
|
logic SCLKenableEarly; //SCLKenable 1 PCLK cycle early, needed for on time register changes when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
|
||||||
|
|
||||||
|
//APB access
|
||||||
|
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||||
|
assign Memwrite = PWRITE & PENABLE & PSEL; // only write in access phase
|
||||||
|
assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock
|
||||||
|
|
||||||
|
//Account for subword read/write circuitry
|
||||||
|
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
|
||||||
|
|
||||||
|
assign Din = PWDATA[31:0];
|
||||||
|
if (P.XLEN == 64) assign PRDATA = {Dout, Dout};
|
||||||
|
else assign PRDATA = Dout;
|
||||||
|
|
||||||
|
//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 {5'b10000};
|
||||||
|
TransmitData <= #1 9'b0;
|
||||||
|
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
|
||||||
|
|
||||||
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
|
if (Memwrite & TransmitInactive)
|
||||||
|
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[2]};
|
||||||
|
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 <= #1 {20'b0, SckDiv};
|
||||||
|
8'h04: Dout <= #1 {30'b0, SckMode};
|
||||||
|
8'h10: Dout <= #1 {30'b0, ChipSelectID};
|
||||||
|
8'h14: Dout <= #1 {28'b0, ChipSelectDef};
|
||||||
|
8'h18: Dout <= #1 {30'b0, ChipSelectMode};
|
||||||
|
8'h28: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]};
|
||||||
|
8'h2C: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]};
|
||||||
|
8'h40: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0};
|
||||||
|
8'h48: Dout <= #1 {23'b0, TransmitFIFOWriteFull, 8'b0};
|
||||||
|
8'h4C: Dout <= #1 {23'b0, ReceiveFIFOReadEmpty, ReceiveData[7:0]};
|
||||||
|
8'h50: Dout <= #1 {29'b0, TransmitWatermark};
|
||||||
|
8'h54: Dout <= #1 {29'b0, ReceiveWatermark};
|
||||||
|
8'h70: Dout <= #1 {30'b0, InterruptEnable};
|
||||||
|
8'h74: Dout <= #1 {30'b0, InterruptPending};
|
||||||
|
default: Dout <= #1 32'b0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
||||||
|
//Generates a high signal at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
||||||
|
assign SCLKenable = (DivCounter == SckDiv);
|
||||||
|
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) DivCounter <= #1 0;
|
||||||
|
else if (SCLKenable) DivCounter <= 0;
|
||||||
|
else DivCounter <= DivCounter + 12'b1;
|
||||||
|
|
||||||
|
//Boolean logic that tracks frame progression
|
||||||
|
assign FrameCompare = (FrameCount < Format[4:1]);
|
||||||
|
assign ReceivePenultimateFrameBoolean = ((FrameCount + 4'b0001) == Format[4:1]);
|
||||||
|
|
||||||
|
//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 ImplicitDelay1 = SckMode[0] ? 9'b0 : 9'b1;
|
||||||
|
assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
|
||||||
|
|
||||||
|
assign CS_SCKCompare = CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1);
|
||||||
|
assign SCK_CSCompare = SCK_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2);
|
||||||
|
assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0}));
|
||||||
|
assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0}));
|
||||||
|
|
||||||
|
//Calculate when tx/rx shift registers are full/empty
|
||||||
|
TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty);
|
||||||
|
ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKenable, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull);
|
||||||
|
|
||||||
|
//Calculate tx/rx fifo write and recieve increment signals
|
||||||
|
assign TransmitFIFOWriteIncrement = (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
||||||
|
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0;
|
||||||
|
else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement;
|
||||||
|
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) ReceiveFIFOReadIncrement <= 0;
|
||||||
|
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||||
|
|
||||||
|
//Tx/Rx FIFOs
|
||||||
|
SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
|
||||||
|
SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
|
||||||
|
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1;
|
||||||
|
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
|
||||||
|
|
||||||
|
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) ReceiveShiftFullDelay <= 0;
|
||||||
|
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 0;
|
||||||
|
else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull;
|
||||||
|
|
||||||
|
assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
|
||||||
|
|
||||||
|
//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 <= 4'b0;
|
||||||
|
|
||||||
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
|
end else if (SCLKenable) begin
|
||||||
|
case (state)
|
||||||
|
CS_INACTIVE: begin
|
||||||
|
CS_SCKCount <= 9'b1;
|
||||||
|
SCK_CSCount <= 9'b10;
|
||||||
|
FrameCount <= 4'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
|
||||||
|
CS_SCKCount <= CS_SCKCount + 9'b1;
|
||||||
|
if (CS_SCKCompare) state <= ACTIVE_0;
|
||||||
|
end
|
||||||
|
ACTIVE_0: begin
|
||||||
|
FrameCount <= FrameCount + 4'b1;
|
||||||
|
state <= ACTIVE_1;
|
||||||
|
end
|
||||||
|
ACTIVE_1: begin
|
||||||
|
InterXFRCount <= 9'b1;
|
||||||
|
if (FrameCompare) state <= ACTIVE_0;
|
||||||
|
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
|
||||||
|
state <= ACTIVE_0;
|
||||||
|
CS_SCKCount <= 9'b1;
|
||||||
|
SCK_CSCount <= 9'b10;
|
||||||
|
FrameCount <= 4'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
|
||||||
|
SCK_CSCount <= SCK_CSCount + 9'b1;
|
||||||
|
if (SCK_CSCompare) state <= INTER_CS;
|
||||||
|
end
|
||||||
|
INTER_CS: begin
|
||||||
|
InterCSCount <= InterCSCount + 9'b1;
|
||||||
|
if (InterCSCompare ) state <= CS_INACTIVE;
|
||||||
|
end
|
||||||
|
INTER_XFR: begin
|
||||||
|
CS_SCKCount <= 9'b1;
|
||||||
|
SCK_CSCount <= 9'b10;
|
||||||
|
FrameCount <= 4'b0;
|
||||||
|
InterCSCount <= 9'b10;
|
||||||
|
InterXFRCount <= InterXFRCount + 9'b1;
|
||||||
|
if (InterXFRCompare & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
|
||||||
|
else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
|
|
||||||
|
assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
|
||||||
|
assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
|
||||||
|
assign sck = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
|
||||||
|
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
|
||||||
|
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
|
||||||
|
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
|
||||||
|
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
|
||||||
|
assign Active0 = (state == ACTIVE_0);
|
||||||
|
|
||||||
|
//Signal tracks which edge of sck to shift data
|
||||||
|
always_comb
|
||||||
|
case(SckMode[1:0])
|
||||||
|
2'b00: ShiftEdge = ~sck & SCLKenable;
|
||||||
|
2'b01: ShiftEdge = (sck & |(FrameCount) & SCLKenable);
|
||||||
|
2'b10: ShiftEdge = sck & SCLKenable;
|
||||||
|
2'b11: ShiftEdge = (~sck & |(FrameCount) & SCLKenable);
|
||||||
|
default: ShiftEdge = sck & SCLKenable;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
//Transmit shift register
|
||||||
|
assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0];
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if(~PRESETn) TransmitShiftReg <= 8'b0;
|
||||||
|
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
|
||||||
|
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
|
||||||
|
|
||||||
|
assign SPIOut = TransmitShiftReg[7];
|
||||||
|
|
||||||
|
//If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
|
||||||
|
//There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges
|
||||||
|
assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
|
||||||
|
|
||||||
|
//Receive shift register
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
||||||
|
else if (SampleEdge & SCLKenable) begin
|
||||||
|
if (~Active) ReceiveShiftReg <= 8'b0;
|
||||||
|
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
|
||||||
|
end
|
||||||
|
|
||||||
|
//Aligns received data and reverses if little-endian
|
||||||
|
assign LeftShiftAmount = 4'h8 - Format[4:1];
|
||||||
|
assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
|
||||||
|
assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0];
|
||||||
|
|
||||||
|
//Interrupt logic: raise interrupt if any enabled interrupts are pending
|
||||||
|
assign SPIIntr = |(InterruptPending & InterruptEnable);
|
||||||
|
|
||||||
|
//Chip select logic
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Pointer FIFO using design elements from "Simulation and Synthesis Techniques
|
||||||
|
for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers
|
||||||
|
are an extra bit larger than address size to determine full/empty conditions.
|
||||||
|
Watermark comparisons use 2's complement subtraction between the M-1 bit pointers,
|
||||||
|
which are also used to address memory
|
||||||
|
*/
|
||||||
|
|
||||||
|
logic [N-1:0] mem[2**M];
|
||||||
|
logic [M:0] rptr, wptr;
|
||||||
|
logic [M:0] rptrnext, wptrnext;
|
||||||
|
logic rempty_val;
|
||||||
|
logic wfull_val;
|
||||||
|
logic [M-1:0] raddr;
|
||||||
|
logic [M-1:0] waddr;
|
||||||
|
|
||||||
|
assign rdata = mem[raddr];
|
||||||
|
always_ff @(posedge PCLK)
|
||||||
|
if (winc & ~wfull) mem[waddr] <= wdata;
|
||||||
|
|
||||||
|
// write and read are enabled
|
||||||
|
always_ff @(posedge PCLK, negedge PRESETn)
|
||||||
|
if (~PRESETn) begin
|
||||||
|
rptr <= 0;
|
||||||
|
wptr <= 0;
|
||||||
|
wfull <= 1'b0;
|
||||||
|
rempty <= 1'b1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (wen) begin
|
||||||
|
wfull <= wfull_val;
|
||||||
|
wptr <= wptrnext;
|
||||||
|
end
|
||||||
|
if (ren) begin
|
||||||
|
rptr <= rptrnext;
|
||||||
|
rempty <= rempty_val;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign raddr = rptr[M-1:0];
|
||||||
|
assign rptrnext = rptr + {3'b0, (rinc & ~rempty)};
|
||||||
|
assign rempty_val = (wptr == rptrnext);
|
||||||
|
assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull;
|
||||||
|
assign waddr = wptr[M-1:0];
|
||||||
|
assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull;
|
||||||
|
assign wptrnext = wptr + {3'b0, (winc & ~wfull)};
|
||||||
|
assign wfull_val = ({~wptrnext[M], wptrnext[M-1:0]} == rptr);
|
||||||
|
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, SCLKenable,
|
||||||
|
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 (SCLKenable) 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
|
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||||
input logic UARTSin, // UART serial input
|
input logic UARTSin, // UART serial input
|
||||||
output logic UARTSout, // UART serial output
|
output logic UARTSout, // UART serial output
|
||||||
input logic SDCIntr
|
input logic SDCIntr,
|
||||||
|
input logic SPIIn,
|
||||||
|
output logic SPIOut,
|
||||||
|
output logic [3:0] SPICS
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
logic [P.XLEN-1:0] HREADRam, HREADSDC;
|
||||||
|
|
||||||
logic [10:0] HSELRegions;
|
logic [11:0] HSELRegions;
|
||||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC, HSELSPI;
|
||||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD;
|
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD, HSELSPID;
|
||||||
logic HRESPRam, HRESPSDC;
|
logic HRESPRam, HRESPSDC;
|
||||||
logic HREADYRam, HRESPSDCD;
|
logic HREADYRam, HRESPSDCD;
|
||||||
logic [P.XLEN-1:0] HREADBootRom;
|
logic [P.XLEN-1:0] HREADBootRom;
|
||||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||||
logic HSELNoneD;
|
logic HSELNoneD;
|
||||||
logic UARTIntr,GPIOIntr;
|
logic UARTIntr,GPIOIntr, SPIIntr;
|
||||||
logic SDCIntM;
|
logic SDCIntM;
|
||||||
|
|
||||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||||
logic [3:0] PSEL, PREADY;
|
logic [4:0] PSEL, PREADY;
|
||||||
logic [31:0] PADDR;
|
logic [31:0] PADDR;
|
||||||
logic [P.XLEN-1:0] PWDATA;
|
logic [P.XLEN-1:0] PWDATA;
|
||||||
logic [P.XLEN/8-1:0] PSTRB;
|
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 [P.XLEN-1:0] HREADBRIDGE;
|
||||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
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);
|
adrdecs #(P) adrdecs(HADDR, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions);
|
||||||
|
|
||||||
// unswizzle HSEL signals
|
// 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
|
// AHB -> APB bridge
|
||||||
ahbapbbridge #(P, 4) ahbapbbridge (
|
ahbapbbridge #(P, 5) ahbapbbridge (
|
||||||
.HCLK, .HRESETn, .HSEL({HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
.HCLK, .HRESETn, .HSEL({HSELSPI, HSELUART, HSELPLIC, HSELCLINT, HSELGPIO}), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HTRANS, .HREADY,
|
||||||
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
|
.HRDATA(HREADBRIDGE), .HRESP(HRESPBRIDGE), .HREADYOUT(HREADYBRIDGE),
|
||||||
.PCLK, .PRESETn, .PSEL, .PWRITE, .PENABLE, .PADDR, .PWDATA, .PSTRB, .PREADY, .PRDATA);
|
.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
|
// on-chip RAM
|
||||||
if (P.UNCORE_RAM_SUPPORTED) begin : 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
|
if (P.PLIC_SUPPORTED == 1) begin : plic
|
||||||
plic_apb #(P) plic(.PCLK, .PRESETn, .PSEL(PSEL[2]), .PADDR(PADDR[27:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
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
|
end else begin : plic
|
||||||
assign MExtInt = 0;
|
assign MExtInt = 0;
|
||||||
assign SExtInt = 0;
|
assign SExtInt = 0;
|
||||||
|
@ -145,6 +148,14 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
||||||
end else begin : uart
|
end else begin : uart
|
||||||
assign UARTSout = 0; assign UARTIntr = 0;
|
assign UARTSout = 0; assign UARTIntr = 0;
|
||||||
end
|
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
|
// AHB Read Multiplexer
|
||||||
assign HRDATA = ({P.XLEN{HSELRamD}} & HREADRam) |
|
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
|
// 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.
|
// device is ready. Hense this register must be selectively enabled by HREADY.
|
||||||
// However on reset None must be seleted.
|
// 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);
|
flopenr #(1) hselbridgedelayreg(HCLK, ~HRESETn, HREADY, HSELBRIDGE, HSELBRIDGED);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -54,11 +54,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
||||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||||
input logic UARTSin, // UART serial data input
|
input logic UARTSin, // UART serial data input
|
||||||
output logic UARTSout, // UART serial data output
|
output logic UARTSout, // UART serial data output
|
||||||
input logic SDCIntr
|
input logic SDCIntr,
|
||||||
|
input logic SPIIn, // SPI pins in
|
||||||
|
output logic SPIOut, // SPI pins out
|
||||||
|
output logic [3:0] SPICS // SPI chip select pins
|
||||||
);
|
);
|
||||||
|
|
||||||
// Uncore signals
|
// Uncore signals
|
||||||
logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore
|
logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore
|
||||||
logic HRESP; // response from AHB
|
logic HRESP; // response from AHB
|
||||||
logic MTimerInt, MSwInt;// timer and software interrupts from CLINT
|
logic MTimerInt, MSwInt;// timer and software interrupts from CLINT
|
||||||
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
||||||
|
@ -80,7 +83,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
||||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||||
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC,
|
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT, .HSELEXTSDC,
|
||||||
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
|
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
|
||||||
.UARTSout, .MTIME_CLINT, .SDCIntr);
|
.UARTSout, .MTIME_CLINT, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -31,3 +31,12 @@ SAIFPOWER
|
||||||
0: switching factor power analysis
|
0: switching factor power analysis
|
||||||
1: RTL simulation driven power analysis.
|
1: RTL simulation driven power analysis.
|
||||||
|
|
||||||
|
-----
|
||||||
|
Extra Tool (PPA)
|
||||||
|
|
||||||
|
To run ppa analysis that hones into target frequency, you can type:
|
||||||
|
python3 ppa/ppaSynth.py from the synthDC directory. This runs a sweep
|
||||||
|
across all modules listed at the bottom of the ppaSynth.py file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# Python regression test for DC
|
||||||
# Madeleine Masser-Frye mmasserfrye@hmc.edu 5/22
|
# Madeleine Masser-Frye mmasserfrye@hmc.edu 5/22
|
||||||
|
# James Stine james.stine@okstate.edu 15 October 2023
|
||||||
|
#
|
||||||
|
|
||||||
import scipy.optimize as opt
|
import scipy.optimize as opt
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -565,6 +569,7 @@ def makeLineLegend():
|
||||||
fullLeg += [lines.Line2D([0], [0], color='black', label='smallest', linestyle='--')]
|
fullLeg += [lines.Line2D([0], [0], color='black', label='smallest', linestyle='--')]
|
||||||
fullLeg += [lines.Line2D([0], [0], color='blue', label='tsmc28', marker='^')]
|
fullLeg += [lines.Line2D([0], [0], color='blue', label='tsmc28', marker='^')]
|
||||||
fullLeg += [lines.Line2D([0], [0], color='green', label='sky90', marker='o')]
|
fullLeg += [lines.Line2D([0], [0], color='green', label='sky90', marker='o')]
|
||||||
|
fullLeg += [lines.Line2D([0], [0], color='green', label='sky130', marker='+')]
|
||||||
fullLeg += [lines.Line2D([0], [0], color='red', label='combined', marker='_')]
|
fullLeg += [lines.Line2D([0], [0], color='red', label='combined', marker='_')]
|
||||||
fig.legend(handles=fullLeg, ncol=5, handlelength=1.4, loc='center')
|
fig.legend(handles=fullLeg, ncol=5, handlelength=1.4, loc='center')
|
||||||
saveStr = './plots/legend.png'
|
saveStr = './plots/legend.png'
|
||||||
|
@ -689,7 +694,7 @@ def makePlotDirectory():
|
||||||
os.makedirs(new_directory)
|
os.makedirs(new_directory)
|
||||||
os.chdir(new_directory)
|
os.chdir(new_directory)
|
||||||
if 'freq' in folder:
|
if 'freq' in folder:
|
||||||
for tech in ['sky90', 'tsmc28']:
|
for tech in ['sky90', 'sky130', 'tsmc28']:
|
||||||
for mod in modules:
|
for mod in modules:
|
||||||
tech_directory = os.path.join(new_directory, tech)
|
tech_directory = os.path.join(new_directory, tech)
|
||||||
mod_directory = os.path.join(tech_directory, mod)
|
mod_directory = os.path.join(tech_directory, mod)
|
||||||
|
@ -702,15 +707,14 @@ def makePlotDirectory():
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
##############################
|
##############################
|
||||||
# set up stuff, global variables
|
# set up stuff, global variables
|
||||||
widths = [8, 16, 32, 64, 128]
|
widths = [8, 16, 32, 64, 128]
|
||||||
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult'] #, 'mux2d', 'mux4d', 'mux8d']
|
modules = ['priorityencoder', 'add', 'csa', 'shiftleft', 'comparator', 'flop', 'mux2', 'mux4', 'mux8', 'mult']
|
||||||
normAddWidth = 32 # divisor to use with N since normalizing to add_32
|
normAddWidth = 32 # divisor to use with N since normalizing to add_32
|
||||||
|
|
||||||
fitDict = {'add': ['cg', 'l', 'l'], 'mult': ['cg', 's', 's'], 'comparator': ['cg', 'l', 'l'], 'csa': ['c', 'l', 'l'], 'shiftleft': ['cg', 'l', 'ln'], 'flop': ['c', 'l', 'l'], 'priorityencoder': ['cg', 'l', 'l']}
|
fitDict = {'add': ['cg', 'l', 'l'], 'mult': ['cg', 's', 's'], 'comparator': ['cg', 'l', 'l'], 'csa': ['c', 'l', 'l'], 'shiftleft': ['cg', 'l', 'ln'], 'flop': ['c', 'l', 'l'], 'priorityencoder': ['cg', 'l', 'l']} fitDict.update(dict.fromkeys(['mux2', 'mux4', 'mux8'], ['cg', 'l', 'l']))
|
||||||
fitDict.update(dict.fromkeys(['mux2', 'mux4', 'mux8'], ['cg', 'l', 'l']))
|
|
||||||
|
|
||||||
TechSpec = namedtuple("TechSpec", "tech color shape delay area lpower denergy")
|
TechSpec = namedtuple("TechSpec", "tech color shape delay area lpower denergy")
|
||||||
techSpecs = [['sky90', 'green', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['tsmc28', 'blue', '^', 12.2e-3, 209.286002, 1060.0, .08153281695882594]]
|
techSpecs = [['sky90', 'green', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['sky130', 'red', 'o', 43.2e-3, 1440.600027, 714.057, 0.658022690438], ['tsmc28', 'blue', '^', 12.2e-3, 209.286002, 1060.0, .08153281695882594]]
|
||||||
techSpecs = [TechSpec(*t) for t in techSpecs]
|
techSpecs = [TechSpec(*t) for t in techSpecs]
|
||||||
combined = TechSpec('combined fit', 'red', '_', 0, 0, 0, 0)
|
combined = TechSpec('combined fit', 'red', '_', 0, 0, 0, 0)
|
||||||
##############################
|
##############################
|
||||||
|
@ -731,7 +735,8 @@ if __name__ == '__main__':
|
||||||
for mod in modules:
|
for mod in modules:
|
||||||
for w in widths:
|
for w in widths:
|
||||||
freqPlot('sky90', mod, w)
|
freqPlot('sky90', mod, w)
|
||||||
freqPlot('tsmc28', mod, w)
|
#freqPlot('sky130', mod, w)
|
||||||
plotPPA(mod, norm=False)
|
#freqPlot('tsmc28', mod, w)
|
||||||
plotPPA(mod, aleOpt=True)
|
#plotPPA(mod, norm=False)
|
||||||
plt.close('all')
|
#plotPPA(mod, aleOpt=True)
|
||||||
|
plt.close('all')
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
# Madeleine Masser-Frye mmasserfrye@hmc.edu 6/22
|
#
|
||||||
|
# Python regression test for DC
|
||||||
|
# Madeleine Masser-Frye mmasserfrye@hmc.edu 5/22
|
||||||
|
# James Stine james.stine@okstate.edu 15 October 2023
|
||||||
|
#
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
|
@ -7,7 +11,9 @@ from multiprocessing import Pool
|
||||||
from ppaAnalyze import synthsfromcsv
|
from ppaAnalyze import synthsfromcsv
|
||||||
|
|
||||||
def runCommand(module, width, tech, freq):
|
def runCommand(module, width, tech, freq):
|
||||||
command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
|
command = "make synth DESIGN={} WIDTH={} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
|
||||||
|
print('here we go')
|
||||||
|
|
||||||
subprocess.Popen(command, shell=True)
|
subprocess.Popen(command, shell=True)
|
||||||
|
|
||||||
def deleteRedundant(synthsToRun):
|
def deleteRedundant(synthsToRun):
|
||||||
|
@ -20,7 +26,7 @@ def deleteRedundant(synthsToRun):
|
||||||
def freqSweep(module, width, tech):
|
def freqSweep(module, width, tech):
|
||||||
synthsToRun = []
|
synthsToRun = []
|
||||||
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
|
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
|
||||||
allSynths = synthsfromcsv('bestSynths.csv')
|
allSynths = synthsfromcsv('ppa/bestSynths.csv')
|
||||||
for synth in allSynths:
|
for synth in allSynths:
|
||||||
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
|
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
|
||||||
f = 1000/synth.delay
|
f = 1000/synth.delay
|
||||||
|
@ -54,20 +60,20 @@ def allCombos(widths, modules, techs, freqs):
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
##### Run specific syntheses
|
##### Run specific syntheses
|
||||||
widths = [8, 16, 32, 64, 128]
|
widths = [8, 16, 32, 64, 128]
|
||||||
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
|
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
|
||||||
techs = ['sky90', 'tsmc28']
|
techs = ['sky90', 'tsmc28']
|
||||||
freqs = [5000]
|
freqs = [5000]
|
||||||
synthsToRun = allCombos(widths, modules, techs, freqs)
|
synthsToRun = allCombos(widths, modules, techs, freqs)
|
||||||
|
|
||||||
##### Run a sweep based on best delay found in existing syntheses
|
##### Run a sweep based on best delay found in existing syntheses
|
||||||
module = 'add'
|
module = 'add'
|
||||||
width = 32
|
width = 32
|
||||||
tech = 'sky90'
|
tech = 'sky90'
|
||||||
synthsToRun = freqSweep(module, width, tech)
|
synthsToRun = freqSweep(module, width, tech)
|
||||||
|
|
||||||
##### Only do syntheses for which a run doesn't already exist
|
##### Only do syntheses for which a run doesn't already exist
|
||||||
synthsToRun = filterRedundant(synthsToRun)
|
synthsToRun = filterRedundant(synthsToRun)
|
||||||
|
|
||||||
pool = Pool(processes=25)
|
pool = Pool(processes=25)
|
||||||
pool.starmap(print, synthsToRun)
|
pool.starmap(runCommand, synthsToRun)
|
||||||
|
|
|
@ -32,17 +32,15 @@ eval file copy -force [glob ${hdl_src}/cvw.sv] {$outputDir/hdl/}
|
||||||
eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/}
|
eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/}
|
||||||
eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/}
|
eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/}
|
||||||
|
|
||||||
# Check if a wrapper is needed (when cvw_t parameters are used)
|
# Check if a wrapper is needed and create it (to pass parameters when cvw_t parameters are used)
|
||||||
set wrapper 0
|
set wrapper 0
|
||||||
if {[eval exec grep "cvw_t" {$outputDir/hdl/$::env(DESIGN).sv}] ne ""} {
|
if {[catch {eval exec grep "cvw_t" $outputDir/hdl/$::env(DESIGN).sv}] == 0} {
|
||||||
|
echo "Creating wrapper"
|
||||||
set wrapper 1
|
set wrapper 1
|
||||||
# make the wrapper
|
# make the wrapper
|
||||||
exec python3 $::env(WALLY)/synthDC/scripts/wrapperGen.py $::env(DESIGN) $outputDir/hdl
|
exec python3 $::env(WALLY)/synthDC/scripts/wrapperGen.py $::env(DESIGN) $outputDir/hdl
|
||||||
}
|
}
|
||||||
|
|
||||||
# Only for FMA class project; comment out when done
|
|
||||||
# eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/}
|
|
||||||
|
|
||||||
# Enables name mapping
|
# Enables name mapping
|
||||||
if { $saifpower == 1 } {
|
if { $saifpower == 1 } {
|
||||||
saif_map -start
|
saif_map -start
|
||||||
|
@ -310,6 +308,8 @@ set filename [format "%s%s" $outputDir "/reports/mindelay.rep"]
|
||||||
redirect $filename { report_timing -capacitance -transition_time -nets -delay_type min -nworst 1 }
|
redirect $filename { report_timing -capacitance -transition_time -nets -delay_type min -nworst 1 }
|
||||||
|
|
||||||
set filename [format "%s%s" $outputDir "/reports/per_module_timing.rep"]
|
set filename [format "%s%s" $outputDir "/reports/per_module_timing.rep"]
|
||||||
|
redirect -append $filename { echo "\n\n\n//// Critical paths through Stall ////\n\n\n" }
|
||||||
|
redirect -append $filename { report_timing -capacitance -transition_time -nets -through {Stall*} -nworst 1 }
|
||||||
redirect -append $filename { echo "\n\n\n//// Critical paths through ifu ////\n\n\n" }
|
redirect -append $filename { echo "\n\n\n//// Critical paths through ifu ////\n\n\n" }
|
||||||
redirect -append $filename { report_timing -capacitance -transition_time -nets -through {ifu/*} -nworst 1 }
|
redirect -append $filename { report_timing -capacitance -transition_time -nets -through {ifu/*} -nworst 1 }
|
||||||
redirect -append $filename { echo "\n\n\n//// Critical paths through ieu ////\n\n\n" }
|
redirect -append $filename { echo "\n\n\n//// Critical paths through ieu ////\n\n\n" }
|
||||||
|
|
|
@ -21,7 +21,7 @@ args=parser.parse_args()
|
||||||
|
|
||||||
fin_path = glob.glob(f"{os.getenv('WALLY')}/src/**/{args.DESIGN}.sv",recursive=True)[0]
|
fin_path = glob.glob(f"{os.getenv('WALLY')}/src/**/{args.DESIGN}.sv",recursive=True)[0]
|
||||||
|
|
||||||
fin = open(fin_path, "r")
|
fin = open(fin_path, "r", encoding='utf-8')
|
||||||
|
|
||||||
lines = fin.readlines()
|
lines = fin.readlines()
|
||||||
|
|
||||||
|
@ -70,4 +70,4 @@ fout.write(buf)
|
||||||
fin.close()
|
fin.close()
|
||||||
fout.close()
|
fout.close()
|
||||||
|
|
||||||
#print(buf)
|
#print(buf)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// shadowmem.sv
|
// DCacheFlushFSM.sv
|
||||||
//
|
//
|
||||||
// Written: David Harris David_Harris@hmc.edu and Ross Thompson ross1728@gmail.com
|
// Written: David Harris David_Harris@hmc.edu and Ross Thompson ross1728@gmail.com
|
||||||
// Modified: 14 June 2023
|
// Modified: 14 June 2023
|
|
@ -217,7 +217,7 @@ module loggers import cvw::*; #(parameter cvw_t P,
|
||||||
logic PCSrcM;
|
logic PCSrcM;
|
||||||
string LogFile;
|
string LogFile;
|
||||||
logic resetD, resetEdge;
|
logic resetD, resetEdge;
|
||||||
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.bpred.bpred.Predictor.DirPredictor.PCSrcE, PCSrcM);
|
flopenrc #(1) PCSrcMReg(clk, reset, dut.core.FlushM, ~dut.core.StallM, dut.core.ifu.PCSrcE, PCSrcM);
|
||||||
flop #(1) ResetDReg(clk, reset, resetD);
|
flop #(1) ResetDReg(clk, reset, resetD);
|
||||||
assign resetEdge = ~reset & resetD;
|
assign resetEdge = ~reset & resetD;
|
||||||
initial begin
|
initial begin
|
||||||
|
|
|
@ -30,11 +30,13 @@ module watchdog #(parameter XLEN, WatchDogTimerThreshold)
|
||||||
);
|
);
|
||||||
|
|
||||||
// check for hang up.
|
// check for hang up.
|
||||||
logic [XLEN-1:0] PCW;
|
logic [XLEN-1:0] PCM, PCW, OldPCW;
|
||||||
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
|
|
||||||
logic [XLEN-1:0] OldPCW;
|
|
||||||
integer WatchDogTimerCount;
|
integer WatchDogTimerCount;
|
||||||
logic WatchDogTimeOut;
|
logic WatchDogTimeOut;
|
||||||
|
|
||||||
|
flopenr #(XLEN) PCMReg(clk, reset, ~dut.core.ifu.StallM, dut.core.ifu.PCE, PCM); // duplicate PCM register because it is not in ifu for all configurations
|
||||||
|
flopenr #(XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, PCM, PCW);
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
OldPCW <= PCW;
|
OldPCW <= PCW;
|
||||||
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
|
if(OldPCW == PCW) WatchDogTimerCount = WatchDogTimerCount + 1'b1;
|
||||||
|
|
|
@ -644,11 +644,11 @@ module testbenchfp;
|
||||||
// Read the first test
|
// Read the first test
|
||||||
initial begin
|
initial begin
|
||||||
//string testname = {`PATH, Tests[TestNum]};
|
//string testname = {`PATH, Tests[TestNum]};
|
||||||
string p = `PATH;
|
static string pp = `PATH;
|
||||||
string testname;
|
string testname;
|
||||||
string tt0;
|
string tt0;
|
||||||
tt0 = $psprintf("%s", Tests[TestNum]);
|
tt0 = $psprintf("%s", Tests[TestNum]);
|
||||||
testname = {p, tt0};
|
testname = {pp, tt0};
|
||||||
$display("Here you are %s", testname);
|
$display("Here you are %s", testname);
|
||||||
$display("\n\nRunning %s vectors ", Tests[TestNum]);
|
$display("\n\nRunning %s vectors ", Tests[TestNum]);
|
||||||
$readmemh(testname, TestVectors);
|
$readmemh(testname, TestVectors);
|
||||||
|
|
|
@ -72,6 +72,7 @@ module testbench;
|
||||||
logic HMASTLOCK;
|
logic HMASTLOCK;
|
||||||
logic HCLK, HRESETn;
|
logic HCLK, HRESETn;
|
||||||
logic [P.XLEN-1:0] PCW;
|
logic [P.XLEN-1:0] PCW;
|
||||||
|
logic [31:0] NextInstrE, InstrM;
|
||||||
|
|
||||||
string ProgramAddrMapFile, ProgramLabelMapFile;
|
string ProgramAddrMapFile, ProgramLabelMapFile;
|
||||||
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
|
integer ProgramAddrLabelArray [string] = '{ "begin_signature" : 0, "tohost" : 0 };
|
||||||
|
@ -81,7 +82,8 @@ module testbench;
|
||||||
|
|
||||||
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||||
logic UARTSin, UARTSout;
|
logic UARTSin, UARTSout;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
logic SDCIntr;
|
logic SDCIntr;
|
||||||
|
|
||||||
logic HREADY;
|
logic HREADY;
|
||||||
|
@ -214,7 +216,7 @@ module testbench;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
|
flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW);
|
||||||
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
|
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW);
|
||||||
|
|
||||||
// check assertions for a legal configuration
|
// check assertions for a legal configuration
|
||||||
riscvassertions #(P) riscvassertions();
|
riscvassertions #(P) riscvassertions();
|
||||||
|
@ -255,13 +257,13 @@ module testbench;
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||||
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.UARTSin, .UARTSout, .SDCIntr);
|
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
|
||||||
|
|
||||||
// Track names of instructions
|
// Track names of instructions
|
||||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||||
dut.core.ifu.InstrRawF[31:0],
|
dut.core.ifu.InstrRawF[31:0],
|
||||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||||
dut.core.ifu.InstrM, InstrW,
|
InstrM, InstrW,
|
||||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// initialize tests
|
// initialize tests
|
||||||
|
@ -298,6 +300,10 @@ module testbench;
|
||||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// Duplicate copy of pipeline registers that are optimized out of some configurations
|
||||||
|
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
|
||||||
|
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
|
||||||
|
|
||||||
// Termination condition
|
// Termination condition
|
||||||
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
|
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
|
||||||
// or sw gp,-56(t0) for new Imperas tests
|
// or sw gp,-56(t0) for new Imperas tests
|
||||||
|
@ -311,7 +317,7 @@ module testbench;
|
||||||
(dut.core.ieu.dp.regf.we3 &
|
(dut.core.ieu.dp.regf.we3 &
|
||||||
dut.core.ieu.dp.regf.a3 == 3 &
|
dut.core.ieu.dp.regf.a3 == 3 &
|
||||||
dut.core.ieu.dp.regf.wd3 == 1)) |
|
dut.core.ieu.dp.regf.wd3 == 1)) |
|
||||||
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
||||||
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
||||||
|
|
||||||
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk),
|
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk),
|
||||||
|
|
|
@ -229,10 +229,16 @@ module testbench;
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////// Cache Issue ///////////////////////////////////
|
/////////////////////////////// Cache Issue ///////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Duplicate copy of pipeline registers that are optimized out of some configurations
|
||||||
|
logic [31:0] NextInstrE, InstrM;
|
||||||
|
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
|
||||||
|
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
|
||||||
|
|
||||||
logic probe;
|
logic probe;
|
||||||
if (NO_SPOOFING)
|
if (NO_SPOOFING)
|
||||||
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
|
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
|
||||||
& testbench.dut.core.InstrM != 32'h14021273
|
& InstrM != 32'h14021273
|
||||||
& testbench.dut.core.InstrValidM;
|
& testbench.dut.core.InstrValidM;
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,7 +282,9 @@ module testbench;
|
||||||
logic SDCCmdOE;
|
logic SDCCmdOE;
|
||||||
logic [3:0] SDCDatIn;
|
logic [3:0] SDCDatIn;
|
||||||
logic SDCIntr;
|
logic SDCIntr;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
|
|
||||||
|
|
||||||
// Hardwire UART, GPIO pins
|
// Hardwire UART, GPIO pins
|
||||||
assign GPIOIN = 0;
|
assign GPIOIN = 0;
|
||||||
|
@ -434,13 +442,10 @@ module testbench;
|
||||||
|
|
||||||
|
|
||||||
// Wally
|
// Wally
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||||
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HRESPEXT, .HCLK,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.HTRANS, .HMASTLOCK,
|
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
|
||||||
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
|
||||||
.UARTSin, .UARTSout,
|
|
||||||
.SDCIntr);
|
|
||||||
|
|
||||||
// W-stage hardware not needed by Wally itself
|
// W-stage hardware not needed by Wally itself
|
||||||
parameter nop = 'h13;
|
parameter nop = 'h13;
|
||||||
|
@ -452,7 +457,7 @@ module testbench;
|
||||||
`define FLUSHW dut.core.FlushW
|
`define FLUSHW dut.core.FlushW
|
||||||
`define STALLW dut.core.StallW
|
`define STALLW dut.core.StallW
|
||||||
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
|
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
|
||||||
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW);
|
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
|
||||||
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
|
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
|
||||||
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
|
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
|
||||||
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
|
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
|
||||||
|
@ -969,7 +974,7 @@ module testbench;
|
||||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||||
dut.core.ifu.InstrRawF[31:0],
|
dut.core.ifu.InstrRawF[31:0],
|
||||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||||
dut.core.ifu.InstrM, InstrW,
|
InstrM, InstrW,
|
||||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// ------------------
|
// ------------------
|
||||||
|
|
|
@ -212,10 +212,16 @@ module testbench;
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////// Cache Issue ///////////////////////////////////
|
/////////////////////////////// Cache Issue ///////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Duplicate copy of pipeline registers that are optimized out of some configurations
|
||||||
|
logic [31:0] NextInstrE, InstrM;
|
||||||
|
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
|
||||||
|
flopenr #(32) InstrMReg(dut.core.clk, dut.core.reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
|
||||||
|
|
||||||
logic probe;
|
logic probe;
|
||||||
if (NO_SPOOFING)
|
if (NO_SPOOFING)
|
||||||
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
|
assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c
|
||||||
& testbench.dut.core.InstrM != 32'h14021273
|
& InstrM != 32'h14021273
|
||||||
& testbench.dut.core.InstrValidM;
|
& testbench.dut.core.InstrValidM;
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,6 +258,8 @@ module testbench;
|
||||||
logic [31:0] GPIOIN;
|
logic [31:0] GPIOIN;
|
||||||
logic [31:0] GPIOOUT, GPIOEN;
|
logic [31:0] GPIOOUT, GPIOEN;
|
||||||
logic UARTSin, UARTSout;
|
logic UARTSin, UARTSout;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
|
|
||||||
// FPGA-specific Stuff
|
// FPGA-specific Stuff
|
||||||
logic SDCIntr;
|
logic SDCIntr;
|
||||||
|
@ -262,13 +270,10 @@ module testbench;
|
||||||
assign SDCIntr = 0;
|
assign SDCIntr = 0;
|
||||||
|
|
||||||
// Wally
|
// Wally
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset, .reset_ext,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||||
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HSELEXTSDC, .HRESPEXT, .HCLK,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HWSTRB, .HSIZE, .HBURST, .HPROT,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.HTRANS, .HMASTLOCK,
|
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
|
||||||
.TIMECLK('0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
|
||||||
.UARTSin, .UARTSout,
|
|
||||||
.SDCIntr);
|
|
||||||
|
|
||||||
// W-stage hardware not needed by Wally itself
|
// W-stage hardware not needed by Wally itself
|
||||||
parameter nop = 'h13;
|
parameter nop = 'h13;
|
||||||
|
@ -280,7 +285,7 @@ module testbench;
|
||||||
`define FLUSHW dut.core.FlushW
|
`define FLUSHW dut.core.FlushW
|
||||||
`define STALLW dut.core.StallW
|
`define STALLW dut.core.StallW
|
||||||
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
|
flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW);
|
||||||
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW);
|
flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW);
|
||||||
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
|
flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW);
|
||||||
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
|
flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW);
|
||||||
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
|
flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW);
|
||||||
|
@ -794,7 +799,7 @@ module testbench;
|
||||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||||
dut.core.ifu.InstrRawF[31:0],
|
dut.core.ifu.InstrRawF[31:0],
|
||||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||||
dut.core.ifu.InstrM, InstrW,
|
InstrM, InstrW,
|
||||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// ------------------
|
// ------------------
|
||||||
|
|
|
@ -70,6 +70,8 @@ module testbench;
|
||||||
logic [3:0] SDCDatIn;
|
logic [3:0] SDCDatIn;
|
||||||
tri1 [3:0] SDCDat;
|
tri1 [3:0] SDCDat;
|
||||||
tri1 SDCCmd;
|
tri1 SDCCmd;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
|
|
||||||
logic HREADY;
|
logic HREADY;
|
||||||
logic HSELEXT;
|
logic HSELEXT;
|
||||||
|
@ -426,10 +428,10 @@ module testbench;
|
||||||
assign SDCDat = '0;
|
assign SDCDat = '0;
|
||||||
end
|
end
|
||||||
|
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||||
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK);
|
.UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn);
|
||||||
|
|
||||||
// generate clock to sequence tests
|
// generate clock to sequence tests
|
||||||
always begin
|
always begin
|
||||||
|
@ -440,20 +442,25 @@ module testbench;
|
||||||
// Support logic
|
// Support logic
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Duplicate copy of pipeline registers that are optimized out of some configurations
|
||||||
|
logic [31:0] NextInstrE, InstrM;
|
||||||
|
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
|
||||||
|
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
|
||||||
|
|
||||||
// Track names of instructions
|
// Track names of instructions
|
||||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||||
logic [31:0] InstrW;
|
logic [31:0] InstrW;
|
||||||
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
|
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW);
|
||||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||||
dut.core.ifu.InstrRawF[31:0],
|
dut.core.ifu.InstrRawF[31:0],
|
||||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||||
dut.core.ifu.InstrM, InstrW,
|
InstrM, InstrW,
|
||||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// watch for problems such as lockup, reading unitialized memory, bad configs
|
// watch for problems such as lockup, reading unitialized memory, bad configs
|
||||||
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
|
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
|
||||||
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
|
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
|
||||||
dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName);
|
dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName);
|
||||||
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
|
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
|
||||||
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
|
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
|
||||||
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
|
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
|
||||||
|
@ -478,7 +485,7 @@ module testbench;
|
||||||
(dut.core.ieu.dp.regf.we3 &
|
(dut.core.ieu.dp.regf.we3 &
|
||||||
dut.core.ieu.dp.regf.a3 == 3 &
|
dut.core.ieu.dp.regf.a3 == 3 &
|
||||||
dut.core.ieu.dp.regf.wd3 == 1)) |
|
dut.core.ieu.dp.regf.wd3 == 1)) |
|
||||||
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
||||||
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
||||||
|
|
||||||
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));
|
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));
|
||||||
|
|
|
@ -64,7 +64,8 @@ module testbench;
|
||||||
|
|
||||||
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||||
logic UARTSin, UARTSout;
|
logic UARTSin, UARTSout;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
logic SDCIntr;
|
logic SDCIntr;
|
||||||
|
|
||||||
logic HREADY;
|
logic HREADY;
|
||||||
|
@ -367,6 +368,7 @@ module testbench;
|
||||||
// instantiate device to be tested
|
// instantiate device to be tested
|
||||||
assign GPIOIN = 0;
|
assign GPIOIN = 0;
|
||||||
assign UARTSin = 1;
|
assign UARTSin = 1;
|
||||||
|
assign SPIIn = 0;
|
||||||
|
|
||||||
if(P.EXT_MEM_SUPPORTED) begin
|
if(P.EXT_MEM_SUPPORTED) begin
|
||||||
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
|
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
|
||||||
|
@ -397,7 +399,7 @@ module testbench;
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC,
|
||||||
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.UARTSin, .UARTSout, .SDCIntr);
|
.UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS);
|
||||||
|
|
||||||
// generate clock to sequence tests
|
// generate clock to sequence tests
|
||||||
always begin
|
always begin
|
||||||
|
@ -408,20 +410,25 @@ module testbench;
|
||||||
// Support logic
|
// Support logic
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Duplicate copy of pipeline registers that are optimized out of some configurations
|
||||||
|
logic [31:0] NextInstrE, InstrM;
|
||||||
|
mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE);
|
||||||
|
flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM);
|
||||||
|
|
||||||
// Track names of instructions
|
// Track names of instructions
|
||||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||||
logic [31:0] InstrW;
|
logic [31:0] InstrW;
|
||||||
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW);
|
flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW);
|
||||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||||
dut.core.ifu.InstrRawF[31:0],
|
dut.core.ifu.InstrRawF[31:0],
|
||||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||||
dut.core.ifu.InstrM, InstrW,
|
InstrM, InstrW,
|
||||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||||
|
|
||||||
// watch for problems such as lockup, reading unitialized memory, bad configs
|
// watch for problems such as lockup, reading unitialized memory, bad configs
|
||||||
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
|
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
|
||||||
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
|
ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM,
|
||||||
dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName);
|
dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName);
|
||||||
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
|
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
|
||||||
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
|
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
|
||||||
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
|
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
|
||||||
|
@ -446,7 +453,7 @@ module testbench;
|
||||||
(dut.core.ieu.dp.regf.we3 &
|
(dut.core.ieu.dp.regf.we3 &
|
||||||
dut.core.ieu.dp.regf.a3 == 3 &
|
dut.core.ieu.dp.regf.a3 == 3 &
|
||||||
dut.core.ieu.dp.regf.wd3 == 1)) |
|
dut.core.ieu.dp.regf.wd3 == 1)) |
|
||||||
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
|
||||||
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
|
||||||
|
|
||||||
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));
|
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));
|
||||||
|
|
|
@ -2010,7 +2010,8 @@ string arch64zbs[] = '{
|
||||||
"rv64i_m/privilege/src/WALLY-gpio-01.S",
|
"rv64i_m/privilege/src/WALLY-gpio-01.S",
|
||||||
"rv64i_m/privilege/src/WALLY-plic-01.S",
|
"rv64i_m/privilege/src/WALLY-plic-01.S",
|
||||||
"rv64i_m/privilege/src/WALLY-plic-s-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[] = '{
|
string wally32e[] = '{
|
||||||
|
@ -2096,7 +2097,8 @@ string arch64zbs[] = '{
|
||||||
"rv32i_m/privilege/src/WALLY-clint-01.S",
|
"rv32i_m/privilege/src/WALLY-clint-01.S",
|
||||||
"rv32i_m/privilege/src/WALLY-uart-01.S",
|
"rv32i_m/privilege/src/WALLY-uart-01.S",
|
||||||
"rv32i_m/privilege/src/WALLY-plic-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"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// testbench.sv
|
// wallywrapper.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 9 January 2021
|
// Written: David_Harris@hmc.edu 9 January 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Wally Testbench and helper modules
|
// Purpose: Wrapper module to define parameters for Wally Verilator linting
|
||||||
// Applies test programs from the riscv-arch-test and Imperas suites
|
|
||||||
//
|
//
|
||||||
// A component of the Wally configurable RISC-V project.
|
// A component of the Wally configurable RISC-V project.
|
||||||
//
|
//
|
||||||
|
@ -51,6 +50,8 @@ module wallywrapper;
|
||||||
|
|
||||||
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
logic [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||||
logic UARTSin, UARTSout;
|
logic UARTSin, UARTSout;
|
||||||
|
logic SPIIn, SPIOut;
|
||||||
|
logic [3:0] SPICS;
|
||||||
logic SDCIntr;
|
logic SDCIntr;
|
||||||
|
|
||||||
logic HREADY;
|
logic HREADY;
|
||||||
|
@ -70,6 +71,6 @@ module wallywrapper;
|
||||||
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
|
wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC,
|
||||||
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
.HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||||
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
|
||||||
.UARTSin, .UARTSout, .SDCIntr);
|
.UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -56,6 +56,7 @@ target_tests_nosim = \
|
||||||
WALLY-clint-01 \
|
WALLY-clint-01 \
|
||||||
WALLY-plic-01 \
|
WALLY-plic-01 \
|
||||||
WALLY-uart-01 \
|
WALLY-uart-01 \
|
||||||
|
WALLY-spi-01 \
|
||||||
WALLY-cbom-01 \
|
WALLY-cbom-01 \
|
||||||
WALLY-cboz-01 \
|
WALLY-cboz-01 \
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
00000003 # reset tests sck_div
|
||||||
|
|
||||||
|
00000000 # sck_mode
|
||||||
|
|
||||||
|
00000000 # cs_id
|
||||||
|
|
||||||
|
0000000F # cs_def
|
||||||
|
|
||||||
|
00000000 # cs_mode
|
||||||
|
|
||||||
|
00010001 # delay 0
|
||||||
|
|
||||||
|
00000001 # delay 1
|
||||||
|
|
||||||
|
00080000 # fmt
|
||||||
|
|
||||||
|
00000000 # tx_data
|
||||||
|
|
||||||
|
00000000 # tx_mark
|
||||||
|
|
||||||
|
00000000 # rx_mark
|
||||||
|
|
||||||
|
00000000 # ie reset
|
||||||
|
|
||||||
|
00000000 # ip reset
|
||||||
|
|
||||||
|
00000000 # fifo watermark and edge case tests
|
||||||
|
|
||||||
|
00000001
|
||||||
|
|
||||||
|
00000003
|
||||||
|
|
||||||
|
00000003
|
||||||
|
|
||||||
|
00000074
|
||||||
|
|
||||||
|
00000063
|
||||||
|
|
||||||
|
00000052
|
||||||
|
|
||||||
|
00000041
|
||||||
|
|
||||||
|
000000A1
|
||||||
|
|
||||||
|
00000003
|
||||||
|
|
||||||
|
000000B2
|
||||||
|
|
||||||
|
00000001
|
||||||
|
|
||||||
|
000000C3
|
||||||
|
|
||||||
|
000000D4
|
||||||
|
|
||||||
|
00000003
|
||||||
|
|
||||||
|
000000A4
|
||||||
|
|
||||||
|
00000001
|
||||||
|
|
||||||
|
000000B4
|
||||||
|
|
||||||
|
000000A5
|
||||||
|
|
||||||
|
000000B5
|
||||||
|
|
||||||
|
000000C5
|
||||||
|
|
||||||
|
000000D5
|
||||||
|
|
||||||
|
000000A7
|
||||||
|
|
||||||
|
000000B7
|
||||||
|
|
||||||
|
000000C7
|
||||||
|
|
||||||
|
00000002
|
||||||
|
|
||||||
|
000000D7
|
||||||
|
|
||||||
|
00000000
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
000000CE hold mode deassert
|
||||||
|
|
||||||
|
000000F0 #fmt register
|
||||||
|
|
||||||
|
00000000
|
||||||
|
|
||||||
|
00000080
|
||||||
|
|
||||||
|
00000000
|
||||||
|
|
||||||
|
00000080
|
||||||
|
|
||||||
|
000000A8
|
||||||
|
|
||||||
|
000000F8
|
||||||
|
|
||||||
|
00000048
|
||||||
|
|
||||||
|
00000070
|
||||||
|
|
||||||
|
00000000
|
||||||
|
|
||||||
|
00000008
|
||||||
|
|
||||||
|
00000003
|
||||||
|
|
||||||
|
00000017
|
||||||
|
|
||||||
|
0000000F
|
||||||
|
|
||||||
|
0000001F
|
||||||
|
|
||||||
|
00000062 # hardware interlock
|
||||||
|
|
||||||
|
00000026
|
||||||
|
|
||||||
|
000000D2
|
||||||
|
|
||||||
|
0000002D
|
||||||
|
|
||||||
|
00000048
|
||||||
|
|
||||||
|
00000037
|
||||||
|
|
||||||
|
00000026
|
||||||
|
|
||||||
|
00000015
|
||||||
|
|
||||||
|
00000084
|
||||||
|
|
||||||
|
00000073
|
||||||
|
|
||||||
|
00000062
|
||||||
|
|
||||||
|
00000051
|
||||||
|
|
||||||
|
00000046
|
||||||
|
|
||||||
|
00000035
|
||||||
|
|
||||||
|
00000024
|
||||||
|
|
||||||
|
00000013
|
||||||
|
|
||||||
|
00000064
|
||||||
|
|
||||||
|
00000053
|
||||||
|
|
||||||
|
00000042
|
||||||
|
|
||||||
|
00000031
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
00000022 #clear frame
|
||||||
|
|
||||||
|
00000000 #read rx ip
|
||||||
|
|
||||||
|
00000000 #read mip 94
|
||||||
|
|
||||||
|
00000002 #read rx ip
|
||||||
|
|
||||||
|
00000800 #read mip
|
||||||
|
|
||||||
|
00000033 #clear frame
|
||||||
|
|
||||||
|
00000000 #read rx wm
|
||||||
|
|
||||||
|
00000000 #read mip 99
|
||||||
|
|
|
@ -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_GPIO, 0x0C00000C # GPIO is interrupt 3
|
||||||
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
|
.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_INTPENDING0, 0x0C001000 # intPending0 register
|
||||||
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
|
.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
|
.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_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_GPIO, 7, write32_test # Set GPIO to high priority
|
||||||
.4byte PLIC_INTPRI_UART, 7, write32_test # Set UART 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_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
|
||||||
.4byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
.4byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
||||||
.endm
|
.endm
|
||||||
|
@ -1028,6 +1030,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||||
sw t3, 0(t2)
|
sw t3, 0(t2)
|
||||||
sw t4, -4(sp)
|
sw t4, -4(sp)
|
||||||
addi sp, sp, -4
|
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 t2, 0x0C002000
|
||||||
li t3, 0x0C200004
|
li t3, 0x0C200004
|
||||||
li t4, 0xFFF
|
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
|
sw t6, 0(t2) // restore saved enable status
|
||||||
li t2, 0x0C00000C // GPIO priority
|
li t2, 0x0C00000C // GPIO priority
|
||||||
li t3, 0x0C000028 // UART priority
|
li t3, 0x0C000028 // UART priority
|
||||||
lw t4, 4(sp) // load stored GPIO and UART priority
|
li t6, 0x0C000018 // SPI priority
|
||||||
lw t5, 0(sp)
|
lw a4, 8(sp) // load stored GPIO prioroty
|
||||||
addi sp, sp, 8 // restore stack pointer
|
lw t4, 4(sp) // load stored UART priority
|
||||||
sw t4, 0(t2)
|
lw t5, 0(sp) // load stored SPI priority
|
||||||
sw t5, 0(t3)
|
addi sp, sp, 12 // restore stack pointer
|
||||||
|
sw a4, 0(t2)
|
||||||
|
sw t4, 0(t3)
|
||||||
|
sw t5, 0(t6)
|
||||||
j test_loop
|
j test_loop
|
||||||
|
|
||||||
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||||
|
@ -1128,6 +1139,34 @@ uart_clearmodemintr:
|
||||||
lb t2, 0(t2)
|
lb t2, 0(t2)
|
||||||
j test_loop
|
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:
|
goto_s_mode:
|
||||||
// return to address in t3,
|
// return to address in t3,
|
||||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||||
|
|
|
@ -0,0 +1,660 @@
|
||||||
|
///////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
# =========== 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, 0x00010001, 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, 0x00080000, 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
|
||||||
|
|
||||||
|
#test watermark interrupts at beginning where fifo read/write pointers are known b/c reset
|
||||||
|
# txwmp raised when # of entries in txfifo < txmark, rxwm raised when # of entries in rxfifo > rxmark
|
||||||
|
|
||||||
|
.4byte ip, 0x00000000, read32_test # txfifo entries not < 0, rxfifo entries not > 0;
|
||||||
|
.4byte tx_mark, 0x00000004, write32_test # set tx_mark to 4
|
||||||
|
.4byte rx_mark, 0x00000003, write32_test # set rx_mark to 3
|
||||||
|
.4byte ip, 0x00000001, read32_test # tx entries < 4, rx entries ! > 3
|
||||||
|
.4byte tx_data, 0x41526374, spi_burst_send
|
||||||
|
.4byte 0x0, 0x00000003, spi_data_wait
|
||||||
|
.4byte ip, 0x00000003, read32_test # tx entries < 4, rx entries > 3, visual inspection should see tx TransmitFIFOReadIncrement
|
||||||
|
|
||||||
|
# txfifo wptr now at 0011, rxfifo wptr at 0000
|
||||||
|
|
||||||
|
.4byte rx_mark, 0x00000007, write32_test # set rx_mark to 7
|
||||||
|
.4byte tx_data, 0xD4C3B2A1, spi_burst_send
|
||||||
|
.4byte 0x0, 0x00000007, spi_data_wait # rxfifo full, txfifo wptr at 1000, rxfifo wptr at 0000
|
||||||
|
.4byte ip, 0x00000003, read32_test
|
||||||
|
.4byte rx_data, 0x00000074, read32_test
|
||||||
|
.4byte rx_data, 0x00000063, read32_test # clear 2 entries, txfifo wptr at 1000, rxfifo wptr at 0010
|
||||||
|
|
||||||
|
|
||||||
|
.4byte tx_data, 0x000000A4, write32_test
|
||||||
|
.4byte tx_data, 0x000000B4, write32_test # tx 1010, rx 0010
|
||||||
|
.4byte 0x0, 0x00000007, spi_data_wait # 8 tx 1010, rx 0010
|
||||||
|
.4byte rx_mark, 0x00000004, write32_test
|
||||||
|
.4byte rx_data, 0x00000052, read32_test # 7 rx 0011
|
||||||
|
.4byte rx_data, 0x00000041, read32_test # 6 rx 0100
|
||||||
|
.4byte rx_data, 0x000000A1, read32_test # 5 rx 0101
|
||||||
|
.4byte ip, 0x00000003, read32_test # 5 things in rx fifo
|
||||||
|
.4byte rx_data, 0x000000B2, read32_test # 4 tx 1010, rx 0110
|
||||||
|
.4byte ip, 0x00000001, read32_test # 4 entries in rxfifo, not strictly greater than 4
|
||||||
|
|
||||||
|
.4byte rx_mark, 0x00000007, write32_test
|
||||||
|
.4byte tx_data, 0xD5C5B5A5, spi_burst_send # 8 tx1110, rx 0110
|
||||||
|
.4byte 0x0, 0x00000007, spi_data_wait
|
||||||
|
|
||||||
|
.4byte rx_mark, 0x00000005, write32_test
|
||||||
|
.4byte rx_data, 0x000000C3, read32_test # tx 1110, rx 0111
|
||||||
|
.4byte rx_data, 0x000000D4, read32_test # tx 1110, rx 1000
|
||||||
|
.4byte ip, 0x00000003, read32_test # 6 entries
|
||||||
|
.4byte rx_data, 0x000000A4, read32_test # tx 1110, rx 1001
|
||||||
|
.4byte ip, 0x00000001, read32_test # 5 entries
|
||||||
|
.4byte rx_data, 0x000000B4, read32_test # tx 1110, rx 1010
|
||||||
|
.4byte rx_data, 0x000000A5, read32_test # tx 1110, rx 1011
|
||||||
|
|
||||||
|
.4byte rx_mark, 0x00000006, write32_test
|
||||||
|
.4byte tx_data, 0xD7C7B7A7, spi_burst_send
|
||||||
|
.4byte 0x0, 0x00000006, spi_data_wait # tx 0010, rx 1011
|
||||||
|
.4byte tx_mark, 0x00000000, write32_test
|
||||||
|
.4byte rx_mark, 0x00000000, write32_test
|
||||||
|
.4byte rx_data, 0x000000B5, read32_test # tx 0010, rx 1100
|
||||||
|
.4byte rx_data, 0x000000C5, read32_test # tx 0010, rx 1101
|
||||||
|
.4byte rx_data, 0x000000D5, read32_test # tx 0010, rx 1110
|
||||||
|
.4byte rx_data, 0x000000A7, read32_test # tx 0010, rx 1111
|
||||||
|
.4byte rx_data, 0x000000B7, read32_test # tx 0010, rx 0000
|
||||||
|
.4byte rx_data, 0x000000C7, read32_test # tx 0010, rx 0001
|
||||||
|
.4byte ip, 0x00000002, read32_test
|
||||||
|
.4byte rx_data, 0x000000D7, read32_test # tx 0010, rx 1010
|
||||||
|
.4byte ip, 0x00000000, read32_test
|
||||||
|
.4byte tx_mark, 0x00000000, write32_test
|
||||||
|
.4byte rx_mark, 0x00000000, write32_test # reset watermark registers
|
||||||
|
|
||||||
|
# =========== 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, 0x00010000, 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, 0x00010005, 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, 0x00010005, 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, 0x00050001, 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, 0x00050001, 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, 0x00010001, write32_test # reset delay0 register
|
||||||
|
.4byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050001, 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, 0x00A50001, write32_test
|
||||||
|
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00010005, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 hold mode deassert conditions
|
||||||
|
|
||||||
|
.4byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||||
|
.4byte delay0, 0x00010001, write32_test # reset delay0 register
|
||||||
|
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
|
||||||
|
.4byte tx_data, 0x000000CE, write32_test # place data into tx_data
|
||||||
|
.4byte cs_id, 0x00000001, write32_test #change selected cs pin. should deassert cs[0] in hold mode
|
||||||
|
.4byte cs_def, 0x0000000D, write32_test # change selected cs pins def value. should deassert cs[1]
|
||||||
|
.4byte cs_mode, 0x00000000, write32_test # change cs_mode to auto, should deassert cs[1], have now gone through all deassertion conditions
|
||||||
|
.4byte cs_def, 0x0000000F, write32_test # reset cs_def
|
||||||
|
.4byte cs_id, 0x00000000, write32_test # reset cs_id
|
||||||
|
.4byte rx_data, 0x000000CE, read32_test # clear rx_fifo
|
||||||
|
|
||||||
|
# =========== Test frame format (fmt) register ===========
|
||||||
|
|
||||||
|
# Test frame length of 4
|
||||||
|
|
||||||
|
.4byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||||
|
.4byte delay0, 0x00010001, 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, 0x00040000, write32_test # set frame length to 4
|
||||||
|
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00010000, write32_test
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050000, write32_test # set frame length to 5, big endian
|
||||||
|
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050004, write32_test # set frame length to 5, little-endian
|
||||||
|
.4byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00080001, 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, 0x00040001, 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, 0x00050001, 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, 0x00050002, 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, 0x00040002, 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, 0x00080002, 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 Hardware Interlock ================
|
||||||
|
|
||||||
|
# interlock in base case
|
||||||
|
|
||||||
|
.4byte fmt, 0x00080000, write32_test # reset fmt register
|
||||||
|
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte tx_data, 0x00000062, write32_test # initiate transmission
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip polarity during transmission
|
||||||
|
.4byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait
|
||||||
|
.4byte rx_data, 0x00000062, read32_test
|
||||||
|
.4byte rx_data, 0x00000026, read32_test # clear rx fifo
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
|
||||||
|
# interlock in case where cs_mode is auto, but there is minimal intercs delay
|
||||||
|
|
||||||
|
.4byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay
|
||||||
|
.4byte tx_data, 0x000000D2, write32_test # initiate transmission
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip sck polarity
|
||||||
|
.4byte tx_data, 0x0000002D, write32_test # transmit second frame
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait
|
||||||
|
.4byte rx_data, 0x000000D2, read32_test
|
||||||
|
.4byte rx_data, 0x0000002D, read32_test # clear rx fifo
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, 0 intercs delay
|
||||||
|
.4byte delay0, 0x00010001, write32_test # reset delay0
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.4byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
|
||||||
|
.4byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.4byte rx_data, 0x00000048, read32_test
|
||||||
|
.4byte rx_data, 0x00000037, read32_test
|
||||||
|
.4byte rx_data, 0x00000026, read32_test
|
||||||
|
.4byte rx_data, 0x00000015, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, intercs delay
|
||||||
|
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.4byte delay1, 0x00010001, write32_test # set intercs delay to 1
|
||||||
|
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.4byte rx_data, 0x00000084, read32_test
|
||||||
|
.4byte rx_data, 0x00000073, read32_test
|
||||||
|
.4byte rx_data, 0x00000062, read32_test
|
||||||
|
.4byte rx_data, 0x00000051, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# repeat previous set of tests with cs_mode = off
|
||||||
|
|
||||||
|
.4byte cs_mode, 0x00000003, write32_test # set cs_mode to hold
|
||||||
|
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.4byte rx_data, 0x00000046, read32_test
|
||||||
|
.4byte rx_data, 0x00000035, read32_test
|
||||||
|
.4byte rx_data, 0x00000024, read32_test
|
||||||
|
.4byte rx_data, 0x00000013, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, intercs delay
|
||||||
|
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.4byte delay1, 0x00000000, write32_test # set intercs delay to 0
|
||||||
|
.4byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.4byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.4byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.4byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.4byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.4byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.4byte rx_data, 0x00000064, read32_test
|
||||||
|
.4byte rx_data, 0x00000053, read32_test
|
||||||
|
.4byte rx_data, 0x00000042, read32_test
|
||||||
|
.4byte rx_data, 0x00000031, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# =========== Test watermark interrupts ===========
|
||||||
|
|
||||||
|
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||||
|
|
||||||
|
SETUP_PLIC
|
||||||
|
|
||||||
|
.4byte delay1, 0x0000001, write32_test # reset delay1 register
|
||||||
|
.4byte cs_mode, 0x00000000, write32_test # reset cs_mode
|
||||||
|
.4byte tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off)
|
||||||
|
#.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 125
|
||||||
|
.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, 0x00000001, write32_test # set transmit watermark to 0
|
||||||
|
.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 # disable tx intr
|
||||||
|
.4byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||||
|
.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 0x0, 0x00000000, claim_m_plic_interrupts
|
||||||
|
.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
|
|
@ -54,6 +54,9 @@ target_tests_nosim = \
|
||||||
WALLY-trap-s-01 \
|
WALLY-trap-s-01 \
|
||||||
WALLY-trap-u-01 \
|
WALLY-trap-u-01 \
|
||||||
WALLY-status-fp-enabled-01 \
|
WALLY-status-fp-enabled-01 \
|
||||||
|
WALLY-spi-01 \
|
||||||
|
WALLY-gpio-01 \
|
||||||
|
WALLY-uart-01 \
|
||||||
WALLY-wfi-01 \
|
WALLY-wfi-01 \
|
||||||
WALLY-cbom-01 \
|
WALLY-cbom-01 \
|
||||||
WALLY-cboz-01 \
|
WALLY-cboz-01 \
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
00000003 # reset tests sck_div
|
||||||
|
00000000
|
||||||
|
00000000 # sck_mode
|
||||||
|
00000000
|
||||||
|
00000000 # cs_id
|
||||||
|
00000000
|
||||||
|
0000000F # cs_def
|
||||||
|
00000000
|
||||||
|
00000000 # cs_mode
|
||||||
|
00000000
|
||||||
|
00010001 # delay 0
|
||||||
|
00000000
|
||||||
|
00000001 # delay 1
|
||||||
|
00000000
|
||||||
|
00080000 # fmt
|
||||||
|
00000000
|
||||||
|
00000000 # tx_data
|
||||||
|
00000000
|
||||||
|
00000000 # tx_mark
|
||||||
|
00000000
|
||||||
|
00000000 # rx_mark
|
||||||
|
00000000
|
||||||
|
00000000 # ie reset
|
||||||
|
00000000
|
||||||
|
00000000 # ip reset
|
||||||
|
00000000
|
||||||
|
00000000 # fifo watermark and edge case tests
|
||||||
|
00000000
|
||||||
|
00000001
|
||||||
|
00000000
|
||||||
|
00000003
|
||||||
|
00000000
|
||||||
|
00000003
|
||||||
|
00000000
|
||||||
|
00000074
|
||||||
|
00000000
|
||||||
|
00000063
|
||||||
|
00000000
|
||||||
|
00000052
|
||||||
|
00000000
|
||||||
|
00000041
|
||||||
|
00000000
|
||||||
|
000000A1
|
||||||
|
00000000
|
||||||
|
00000003
|
||||||
|
00000000
|
||||||
|
000000B2
|
||||||
|
00000000
|
||||||
|
00000001
|
||||||
|
00000000
|
||||||
|
000000C3
|
||||||
|
00000000
|
||||||
|
000000D4
|
||||||
|
00000000
|
||||||
|
00000003
|
||||||
|
00000000
|
||||||
|
000000A4
|
||||||
|
00000000
|
||||||
|
00000001
|
||||||
|
00000000
|
||||||
|
000000B4
|
||||||
|
00000000
|
||||||
|
000000A5
|
||||||
|
00000000
|
||||||
|
000000B5
|
||||||
|
00000000
|
||||||
|
000000C5
|
||||||
|
00000000
|
||||||
|
000000D5
|
||||||
|
00000000
|
||||||
|
000000A7
|
||||||
|
00000000
|
||||||
|
000000B7
|
||||||
|
00000000
|
||||||
|
000000C7
|
||||||
|
00000000
|
||||||
|
00000002
|
||||||
|
00000000
|
||||||
|
000000D7
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
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
|
||||||
|
000000CE hold mode deassert
|
||||||
|
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
|
||||||
|
00000062 # hardware interlock
|
||||||
|
00000000
|
||||||
|
00000026
|
||||||
|
00000000
|
||||||
|
000000D2
|
||||||
|
00000000
|
||||||
|
0000002D
|
||||||
|
00000000
|
||||||
|
00000048
|
||||||
|
00000000
|
||||||
|
00000037
|
||||||
|
00000000
|
||||||
|
00000026
|
||||||
|
00000000
|
||||||
|
00000015
|
||||||
|
00000000
|
||||||
|
00000084
|
||||||
|
00000000
|
||||||
|
00000073
|
||||||
|
00000000
|
||||||
|
00000062
|
||||||
|
00000000
|
||||||
|
00000051
|
||||||
|
00000000
|
||||||
|
00000046
|
||||||
|
00000000
|
||||||
|
00000035
|
||||||
|
00000000
|
||||||
|
00000024
|
||||||
|
00000000
|
||||||
|
00000013
|
||||||
|
00000000
|
||||||
|
00000064
|
||||||
|
00000000
|
||||||
|
00000053
|
||||||
|
00000000
|
||||||
|
00000042
|
||||||
|
00000000
|
||||||
|
00000031
|
||||||
|
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
|
||||||
|
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
|
|
@ -886,6 +886,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_GPIO, 0x0C00000C # GPIO is interrupt 3
|
||||||
.equ PLIC_INTPRI_UART, 0x0C000028 # UART is interrupt 10
|
.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_INTPENDING0, 0x0C001000 # intPending0 register
|
||||||
.equ PLIC_INTEN00, 0x0C002000 # interrupt enables for context 0 (machine mode) sources 31:1
|
.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
|
.equ PLIC_INTEN10, 0x0C002080 # interrupt enables for context 1 (supervisor mode) sources 31:1
|
||||||
|
@ -898,6 +899,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_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_GPIO, 7, write32_test # Set GPIO to high priority
|
||||||
.8byte PLIC_INTPRI_UART, 7, write32_test # Set UART 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_INTEN00, 0xFFFFFFFF, write32_test # Enable all interrupt sources for machine mode
|
||||||
.8byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
.8byte PLIC_INTEN10, 0x00000000, write32_test # Disable all interrupt sources for supervisor mode
|
||||||
.endm
|
.endm
|
||||||
|
@ -1067,6 +1069,12 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||||
sw t3, 0(t2)
|
sw t3, 0(t2)
|
||||||
sw t4, -4(sp)
|
sw t4, -4(sp)
|
||||||
addi sp, sp, -4
|
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 t2, 0x0C002000
|
||||||
li t3, 0x0C200004
|
li t3, 0x0C200004
|
||||||
li t4, 0xFFF
|
li t4, 0xFFF
|
||||||
|
@ -1077,11 +1085,14 @@ claim_m_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||||
sw t6, 0(t2) // restore saved enable status
|
sw t6, 0(t2) // restore saved enable status
|
||||||
li t2, 0x0C00000C // GPIO priority
|
li t2, 0x0C00000C // GPIO priority
|
||||||
li t3, 0x0C000028 // UART priority
|
li t3, 0x0C000028 // UART priority
|
||||||
lw t4, 4(sp) // load stored GPIO and UART priority
|
li t6, 0x0C000018 // SPI priority
|
||||||
lw t5, 0(sp)
|
lw a4, 8(sp) // load stored GPIO prioroty
|
||||||
addi sp, sp, 8 // restore stack pointer
|
lw t4, 4(sp) // load stored UART priority
|
||||||
sw t4, 0(t2)
|
lw t5, 0(sp) // load stored SPI priority
|
||||||
sw t5, 0(t3)
|
addi sp, sp, 12 // restore stack pointer
|
||||||
|
sw a4, 0(t2)
|
||||||
|
sw t4, 0(t3)
|
||||||
|
sw t5, 0(t6)
|
||||||
j test_loop
|
j test_loop
|
||||||
|
|
||||||
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
claim_s_plic_interrupts: // clears one non-pending PLIC interrupt
|
||||||
|
@ -1167,6 +1178,34 @@ uart_clearmodemintr:
|
||||||
lb t2, 0(t2)
|
lb t2, 0(t2)
|
||||||
j test_loop
|
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:
|
goto_s_mode:
|
||||||
// return to address in t3,
|
// return to address in t3,
|
||||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||||
|
|
|
@ -0,0 +1,662 @@
|
||||||
|
///////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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, 0x00010001, 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, 0x00080000, 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
|
||||||
|
|
||||||
|
# =========== watermark interrupts ===============
|
||||||
|
|
||||||
|
#test watermark interrupts at beginning where fifo read/write pointers are known b/c reset
|
||||||
|
# txwmp raised when # of entries in txfifo < txmark, rxwm raised when # of entries in rxfifo > rxmark
|
||||||
|
|
||||||
|
.8byte ip, 0x00000000, read32_test # txfifo entries not < 0, rxfifo entries not > 0;
|
||||||
|
.8byte tx_mark, 0x00000004, write32_test # set tx_mark to 4
|
||||||
|
.8byte rx_mark, 0x00000003, write32_test # set rx_mark to 3
|
||||||
|
.8byte ip, 0x00000001, read32_test # tx entries < 4, rx entries ! > 3
|
||||||
|
.8byte tx_data, 0x41526374, spi_burst_send
|
||||||
|
.8byte 0x0, 0x00000003, spi_data_wait
|
||||||
|
.8byte ip, 0x00000003, read32_test # tx entries < 4, rx entries > 3, visual inspection should see tx TransmitFIFOReadIncrement
|
||||||
|
|
||||||
|
# txfifo wptr now at 0011, rxfifo wptr at 0000
|
||||||
|
|
||||||
|
.8byte rx_mark, 0x00000007, write32_test # set rx_mark to 7
|
||||||
|
.8byte tx_data, 0xD4C3B2A1, spi_burst_send
|
||||||
|
.8byte 0x0, 0x00000007, spi_data_wait # rxfifo full, txfifo wptr at 1000, rxfifo wptr at 0000
|
||||||
|
.8byte ip, 0x00000003, read32_test
|
||||||
|
.8byte rx_data, 0x00000074, read32_test
|
||||||
|
.8byte rx_data, 0x00000063, read32_test # clear 2 entries, txfifo wptr at 1000, rxfifo wptr at 0010
|
||||||
|
|
||||||
|
|
||||||
|
.8byte tx_data, 0x000000A4, write32_test
|
||||||
|
.8byte tx_data, 0x000000B4, write32_test # tx 1010, rx 0010
|
||||||
|
.8byte 0x0, 0x00000007, spi_data_wait # 8 tx 1010, rx 0010
|
||||||
|
.8byte rx_mark, 0x00000004, write32_test
|
||||||
|
.8byte rx_data, 0x00000052, read32_test # 7 rx 0011
|
||||||
|
.8byte rx_data, 0x00000041, read32_test # 6 rx 0100
|
||||||
|
.8byte rx_data, 0x000000A1, read32_test # 5 rx 0101
|
||||||
|
.8byte ip, 0x00000003, read32_test # 5 things in rx fifo
|
||||||
|
.8byte rx_data, 0x000000B2, read32_test # 4 tx 1010, rx 0110
|
||||||
|
.8byte ip, 0x00000001, read32_test # 4 entries in rxfifo, not strictly greater than 4
|
||||||
|
|
||||||
|
.8byte rx_mark, 0x00000007, write32_test
|
||||||
|
.8byte tx_data, 0xD5C5B5A5, spi_burst_send # 8 tx1110, rx 0110
|
||||||
|
.8byte 0x0, 0x00000007, spi_data_wait
|
||||||
|
|
||||||
|
.8byte rx_mark, 0x00000005, write32_test
|
||||||
|
.8byte rx_data, 0x000000C3, read32_test # tx 1110, rx 0111
|
||||||
|
.8byte rx_data, 0x000000D4, read32_test # tx 1110, rx 1000
|
||||||
|
.8byte ip, 0x00000003, read32_test # 6 entries
|
||||||
|
.8byte rx_data, 0x000000A4, read32_test # tx 1110, rx 1001
|
||||||
|
.8byte ip, 0x00000001, read32_test # 5 entries
|
||||||
|
.8byte rx_data, 0x000000B4, read32_test # tx 1110, rx 1010
|
||||||
|
.8byte rx_data, 0x000000A5, read32_test # tx 1110, rx 1011
|
||||||
|
|
||||||
|
.8byte rx_mark, 0x00000006, write32_test
|
||||||
|
.8byte tx_data, 0xD7C7B7A7, spi_burst_send
|
||||||
|
.8byte 0x0, 0x00000006, spi_data_wait # tx 0010, rx 1011
|
||||||
|
.8byte tx_mark, 0x00000000, write32_test
|
||||||
|
.8byte rx_mark, 0x00000000, write32_test
|
||||||
|
.8byte rx_data, 0x000000B5, read32_test # tx 0010, rx 1100
|
||||||
|
.8byte rx_data, 0x000000C5, read32_test # tx 0010, rx 1101
|
||||||
|
.8byte rx_data, 0x000000D5, read32_test # tx 0010, rx 1110
|
||||||
|
.8byte rx_data, 0x000000A7, read32_test # tx 0010, rx 1111
|
||||||
|
.8byte rx_data, 0x000000B7, read32_test # tx 0010, rx 0000
|
||||||
|
.8byte rx_data, 0x000000C7, read32_test # tx 0010, rx 0001
|
||||||
|
.8byte ip, 0x00000002, read32_test
|
||||||
|
.8byte rx_data, 0x000000D7, read32_test # tx 0010, rx 1010
|
||||||
|
.8byte ip, 0x00000000, read32_test
|
||||||
|
.8byte tx_mark, 0x00000000, write32_test
|
||||||
|
.8byte rx_mark, 0x00000000, write32_test # reset watermark registers
|
||||||
|
|
||||||
|
# =========== 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, 0x00010000, 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, 0x00010005, 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, 0x00010005, 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, 0x00050001, 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, 0x00050001, 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, 0x00010001, write32_test # reset delay0 register
|
||||||
|
.8byte delay1, 0x00000005, write32_test # set inter_cs delay to 5
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050001, 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, 0x00A50001, write32_test
|
||||||
|
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00010005, write32_test # set cs-sck delay to 5 (should have no effect because cs is never inactive)
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 hold mode deassert conditions
|
||||||
|
|
||||||
|
.8byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||||
|
.8byte delay0, 0x00010001, write32_test # reset delay0 register
|
||||||
|
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
|
||||||
|
.8byte tx_data, 0x000000CE, write32_test # place data into tx_data
|
||||||
|
.8byte cs_id, 0x00000001, write32_test #change selected cs pin. should deassert cs[0] in hold mode
|
||||||
|
.8byte cs_def, 0x0000000D, write32_test # change selected cs pins def value. should deassert cs[1]
|
||||||
|
.8byte cs_mode, 0x00000000, write32_test # change cs_mode to auto, should deassert cs[1], have now gone through all deassertion conditions
|
||||||
|
.8byte cs_def, 0x0000000F, write32_test # reset cs_def
|
||||||
|
.8byte cs_id, 0x00000000, write32_test # reset cs_id
|
||||||
|
.8byte rx_data, 0x000000CE, read32_test # clear rx_fifo
|
||||||
|
|
||||||
|
# =========== Test frame format (fmt) register ===========
|
||||||
|
|
||||||
|
# Test frame length of 4
|
||||||
|
|
||||||
|
.8byte delay1, 0x00000001, write32_test # reset delay1 register
|
||||||
|
.8byte delay0, 0x00010001, 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, 0x00040000, write32_test # set frame length to 4
|
||||||
|
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00010000, write32_test
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050000, write32_test # set frame length to 5, big endian
|
||||||
|
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00050004, write32_test # set frame length to 5, little-endian
|
||||||
|
.8byte rx_mark, 0x0000000, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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 rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.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, 0x00080001, 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, 0x00040001, 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, 0x00050001, 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, 0x00050002, 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, 0x00040002, 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, 0x00080002, 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 Hardware Interlock ================
|
||||||
|
|
||||||
|
# interlock in base case
|
||||||
|
|
||||||
|
.8byte fmt, 0x00080000, write32_test # reset fmt register
|
||||||
|
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte tx_data, 0x00000062, write32_test # initiate transmission
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip polarity during transmission
|
||||||
|
.8byte tx_data, 0x00000026, write32_test # transmit second frame w/ control register updated
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait
|
||||||
|
.8byte rx_data, 0x00000062, read32_test
|
||||||
|
.8byte rx_data, 0x00000026, read32_test # clear rx fifo
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
|
||||||
|
# interlock in case where cs_mode is auto, but there is minimal intercs delay
|
||||||
|
|
||||||
|
.8byte delay0, 0x00000001, write32_test # set sck-cs delay to 0, with sck.pha 0 there is 0 delay
|
||||||
|
.8byte tx_data, 0x000000D2, write32_test # initiate transmission
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip sck polarity
|
||||||
|
.8byte tx_data, 0x0000002D, write32_test # transmit second frame
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait
|
||||||
|
.8byte rx_data, 0x000000D2, read32_test
|
||||||
|
.8byte rx_data, 0x0000002D, read32_test # clear rx fifo
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, 0 intercs delay
|
||||||
|
.8byte delay0, 0x00010001, write32_test # reset delay0
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.8byte cs_mode, 0x00000002, write32_test # set cs_mode to hold
|
||||||
|
.8byte tx_data, 0x15263748, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.8byte rx_data, 0x00000048, read32_test
|
||||||
|
.8byte rx_data, 0x00000037, read32_test
|
||||||
|
.8byte rx_data, 0x00000026, read32_test
|
||||||
|
.8byte rx_data, 0x00000015, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, intercs delay
|
||||||
|
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.8byte delay1, 0x00010001, write32_test # set intercs delay to 1
|
||||||
|
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte tx_data, 0x51627384, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.8byte rx_data, 0x00000084, read32_test
|
||||||
|
.8byte rx_data, 0x00000073, read32_test
|
||||||
|
.8byte rx_data, 0x00000062, read32_test
|
||||||
|
.8byte rx_data, 0x00000051, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# repeat previous set of tests with cs_mode = off
|
||||||
|
|
||||||
|
.8byte cs_mode, 0x00000003, write32_test # set cs_mode to hold
|
||||||
|
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte tx_data, 0x13243546, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.8byte rx_data, 0x00000046, read32_test
|
||||||
|
.8byte rx_data, 0x00000035, read32_test
|
||||||
|
.8byte rx_data, 0x00000024, read32_test
|
||||||
|
.8byte rx_data, 0x00000013, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
# interlock in case where cs_mode = hold, intercs delay
|
||||||
|
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # reset polarity
|
||||||
|
.8byte delay1, 0x00000000, write32_test # set intercs delay to 0
|
||||||
|
.8byte rx_mark, 0x0000001, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte tx_data, 0x31425364, spi_burst_send # place 4 frames into tx fifo
|
||||||
|
.8byte sck_mode, 0x00000002, write32_test # flip polarity (should change 2 second frame)
|
||||||
|
.8byte 0x0, 0x00000001, spi_data_wait # wait for second transmission to end
|
||||||
|
.8byte rx_mark, 0x0000003, write32_test # preset rx watermark b/c of hardware interlock
|
||||||
|
.8byte sck_mode, 0x00000000, write32_test # flip polarity again
|
||||||
|
.8byte 0x0, 0x00000003, spi_data_wait # wait for final frame
|
||||||
|
.8byte rx_data, 0x00000064, read32_test
|
||||||
|
.8byte rx_data, 0x00000053, read32_test
|
||||||
|
.8byte rx_data, 0x00000042, read32_test
|
||||||
|
.8byte rx_data, 0x00000031, read32_test #clear rx fifo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# =========== Test watermark interrupts ===========
|
||||||
|
|
||||||
|
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||||
|
|
||||||
|
SETUP_PLIC
|
||||||
|
|
||||||
|
.8byte delay1, 0x0000001, write32_test # reset delay1 register
|
||||||
|
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode
|
||||||
|
.8byte tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off)
|
||||||
|
#.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 125
|
||||||
|
.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, 0x00000001, write32_test # set transmit watermark to 0
|
||||||
|
.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 ie, 0x00000000, write32_test # disable tx intr
|
||||||
|
.8byte tx_data, 0x55443322, spi_burst_send # place 4 entries in transmit fifo
|
||||||
|
.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 0x0, 0x00000000, claim_m_plic_interrupts
|
||||||
|
.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…
Add table
Add a link
Reference in a new issue