mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw into fetch_buffer
This commit is contained in:
commit
250a8f2f5e
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -25,9 +25,10 @@
|
|||||||
sparseCheckout = true
|
sparseCheckout = true
|
||||||
path = addins/verilog-ethernet
|
path = addins/verilog-ethernet
|
||||||
url = https://github.com/rosethompson/verilog-ethernet.git
|
url = https://github.com/rosethompson/verilog-ethernet.git
|
||||||
[submodule "cvw-arch-verif"]
|
[submodule "addins/cvw-arch-verif"]
|
||||||
path = addins/cvw-arch-verif
|
path = addins/cvw-arch-verif
|
||||||
url = https://github.com/openhwgroup/cvw-arch-verif
|
url = https://github.com/openhwgroup/cvw-arch-verif
|
||||||
|
ignore = dirty
|
||||||
[submodule "addins/riscvISACOV"]
|
[submodule "addins/riscvISACOV"]
|
||||||
path = addins/riscvISACOV
|
path = addins/riscvISACOV
|
||||||
url = https://github.com/riscv-verification/riscvISACOV.git
|
url = https://github.com/riscv-verification/riscvISACOV.git
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit bbcba78647080dee82e96bc1b8ff9cd9a3cf7fa1
|
Subproject commit 6d658b7b42c83fd584008d72964cc75d0876b769
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit ce04b4930545ae4c81e2f3b6f6935e2aac08679e
|
Subproject commit 3843c736e427a2b52a0d06e6220b073afa4be401
|
||||||
@ -10,6 +10,9 @@
|
|||||||
`include "RV32M_coverage.svh"
|
`include "RV32M_coverage.svh"
|
||||||
`include "RV32F_coverage.svh"
|
`include "RV32F_coverage.svh"
|
||||||
`include "RV32D_coverage.svh"
|
`include "RV32D_coverage.svh"
|
||||||
|
`include "RV32ZfaF_coverage.svh"
|
||||||
|
`include "RV32ZfaD_coverage.svh"
|
||||||
|
`include "RV32ZfaZfh_coverage.svh"
|
||||||
`include "RV32ZfhD_coverage.svh"
|
`include "RV32ZfhD_coverage.svh"
|
||||||
`include "RV32Zfh_coverage.svh"
|
`include "RV32Zfh_coverage.svh"
|
||||||
`include "RV32Zicond_coverage.svh"
|
`include "RV32Zicond_coverage.svh"
|
||||||
@ -22,3 +25,5 @@
|
|||||||
|
|
||||||
// Privileged extensions
|
// Privileged extensions
|
||||||
`include "ZicsrM_coverage.svh"
|
`include "ZicsrM_coverage.svh"
|
||||||
|
`include "RV32VM_coverage.svh"
|
||||||
|
`include "RV32VM_PMP_coverage.svh"
|
||||||
|
|||||||
@ -10,6 +10,9 @@
|
|||||||
`include "RV64M_coverage.svh"
|
`include "RV64M_coverage.svh"
|
||||||
`include "RV64F_coverage.svh"
|
`include "RV64F_coverage.svh"
|
||||||
`include "RV64D_coverage.svh"
|
`include "RV64D_coverage.svh"
|
||||||
|
`include "RV64ZfaF_coverage.svh"
|
||||||
|
`include "RV32ZfaD_coverage.svh"
|
||||||
|
`include "RV32ZfaZfh_coverage.svh"
|
||||||
`include "RV64ZfhD_coverage.svh"
|
`include "RV64ZfhD_coverage.svh"
|
||||||
`include "RV64Zfh_coverage.svh"
|
`include "RV64Zfh_coverage.svh"
|
||||||
`include "RV64Zicond_coverage.svh"
|
`include "RV64Zicond_coverage.svh"
|
||||||
|
|||||||
@ -5,3 +5,22 @@ wally/wallypipelinedcore.sv: logic InstrM
|
|||||||
lsu/lsu.sv: logic IEUAdrM
|
lsu/lsu.sv: logic IEUAdrM
|
||||||
lsu/lsu.sv: logic MemRWM
|
lsu/lsu.sv: logic MemRWM
|
||||||
mmu/hptw.sv: logic SATP_REGW
|
mmu/hptw.sv: logic SATP_REGW
|
||||||
|
uncore/spi_apb.sv: logic ShiftIn
|
||||||
|
uncore/spi_apb.sv: logic ReceiveShiftReg
|
||||||
|
uncore/spi_apb.sv: logic SCLKenable
|
||||||
|
uncore/spi_apb.sv: logic SampleEdge
|
||||||
|
uncore/spi_apb.sv: logic Active
|
||||||
|
uncore/spi_apb.sv: statetype state
|
||||||
|
uncore/spi_apb.sv: typedef rsrstatetype
|
||||||
|
uncore/spi_apb.sv: logic SPICLK
|
||||||
|
uncore/spi_apb.sv: logic SPIOut
|
||||||
|
uncore/spi_apb.sv: logic SPICS
|
||||||
|
uncore/spi_apb.sv: logic SckMode
|
||||||
|
uncore/spi_apb.sv: logic SckDiv
|
||||||
|
uncore/spi_apb.sv: logic ShiftEdge
|
||||||
|
uncore/spi_apb.sv: logic TransmitShiftRegLoad
|
||||||
|
uncore/spi_apb.sv: logic TransmitShiftReg
|
||||||
|
uncore/spi_apb.sv: logic TransmitData
|
||||||
|
uncore/spi_apb.sv: logic ReceiveData
|
||||||
|
uncore/spi_apb.sv: logic ReceiveShiftRegEndian
|
||||||
|
uncore/spi_apb.sv: logic ASR
|
||||||
|
|||||||
@ -191,7 +191,6 @@ set_property port_width 1 [get_debug_ports u_ila_0/probe33]
|
|||||||
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe33]
|
set_property PROBE_TYPE DATA_AND_TRIGGER [get_debug_ports u_ila_0/probe33]
|
||||||
connect_debug_port u_ila_0/probe33 [get_nets [list {wallypipelinedsoc/uncoregen.uncore/sdc.sdc/TransmitFIFOReadEmpty} ]]
|
connect_debug_port u_ila_0/probe33 [get_nets [list {wallypipelinedsoc/uncoregen.uncore/sdc.sdc/TransmitFIFOReadEmpty} ]]
|
||||||
|
|
||||||
|
|
||||||
# the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock.
|
# the debug hub has issues with the clocks from the mmcm so lets give up an connect to the 100Mhz input clock.
|
||||||
#connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk]
|
#connect_debug_port dbg_hub/clk [get_nets default_100mhz_clk]
|
||||||
connect_debug_port dbg_hub/clk [get_nets CPUCLK]
|
connect_debug_port dbg_hub/clk [get_nets CPUCLK]
|
||||||
|
|||||||
@ -69,8 +69,8 @@ PreProcessFiles:
|
|||||||
./insert_debug_comment.sh
|
./insert_debug_comment.sh
|
||||||
# This line allows the Bootloader to be loaded in a Block RAM on the FPGA
|
# This line allows the Bootloader to be loaded in a Block RAM on the FPGA
|
||||||
sed -i "s/bit \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
|
sed -i "s/bit \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
|
||||||
sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
|
sed -i 's/$$WALLY/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv
|
||||||
sed -i 's/$$WALLY/\.\.\/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/ram1p1rwbe.sv
|
sed -i 's/$$WALLY/\.\.\/\.\.\//g' ../src/CopiedFiles_do_not_add_to_repo/generic/mem/ram1p1rwbe.sv
|
||||||
|
|
||||||
# build the Zero stage boot loader (ZSBL)
|
# build the Zero stage boot loader (ZSBL)
|
||||||
.PHONY: zsbl
|
.PHONY: zsbl
|
||||||
|
|||||||
@ -102,7 +102,8 @@ if {$board=="ArtyA7"} {
|
|||||||
} else {
|
} else {
|
||||||
#source ../constraints/vcu-small-debug.xdc
|
#source ../constraints/vcu-small-debug.xdc
|
||||||
#source ../constraints/small-debug.xdc
|
#source ../constraints/small-debug.xdc
|
||||||
source ../constraints/small-debug-spi.xdc
|
#source ../constraints/small-debug.xdc
|
||||||
|
source ../constraints/big-debug-spi.xdc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -135,45 +135,45 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) {
|
|||||||
/* crc = crc16(crc, x); */
|
/* crc = crc16(crc, x); */
|
||||||
/* } while (--n > 0); */
|
/* } while (--n > 0); */
|
||||||
|
|
||||||
/* n = 512/8; */
|
n = 512/8;
|
||||||
/* do { */
|
do {
|
||||||
/* // Send 8 dummy bytes (fifo should be empty) */
|
// Send 8 dummy bytes (fifo should be empty)
|
||||||
/* for (j = 0; j < 8; j++) { */
|
|
||||||
/* spi_sendbyte(0xff); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* // Reset counter. Process bytes AS THEY COME IN. */
|
|
||||||
/* for (j = 0; j < 8; j++) { */
|
|
||||||
/* while (!(read_reg(SPI_IP) & 2)) {} */
|
|
||||||
/* uint8_t x = spi_readbyte(); */
|
|
||||||
/* *p++ = x; */
|
|
||||||
/* // crc = crc16(crc, x); */
|
|
||||||
/* crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; */
|
|
||||||
/* } */
|
|
||||||
/* } while(--n > 0); */
|
|
||||||
|
|
||||||
n = 512;
|
|
||||||
// Initially fill the transmit fifo
|
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
spi_sendbyte(0xff);
|
spi_sendbyte(0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset counter. Process bytes AS THEY COME IN.
|
||||||
while (n > 0) {
|
for (j = 0; j < 8; j++) {
|
||||||
// Wait for bytes to be received
|
|
||||||
while (!(read_reg(SPI_IP) & 2)) {}
|
while (!(read_reg(SPI_IP) & 2)) {}
|
||||||
// Read byte
|
|
||||||
uint8_t x = spi_readbyte();
|
uint8_t x = spi_readbyte();
|
||||||
// Send another dummy byte
|
|
||||||
if (n > 8) {
|
|
||||||
spi_sendbyte(0xff);
|
|
||||||
}
|
|
||||||
// Place received byte into memory
|
|
||||||
*p++ = x;
|
*p++ = x;
|
||||||
// Update CRC16 with fast table based method
|
// crc = crc16(crc, x);
|
||||||
crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff;
|
crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff;
|
||||||
n = n - 1;
|
|
||||||
}
|
}
|
||||||
|
} while(--n > 0);
|
||||||
|
|
||||||
|
/* n = 512; */
|
||||||
|
/* // Initially fill the transmit fifo */
|
||||||
|
/* for (j = 0; j < 8; j++) { */
|
||||||
|
/* spi_sendbyte(0xff); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
/* while (n > 0) { */
|
||||||
|
/* // Wait for bytes to be received */
|
||||||
|
/* while (!(read_reg(SPI_IP) & 2)) {} */
|
||||||
|
/* // Read byte */
|
||||||
|
/* uint8_t x = spi_readbyte(); */
|
||||||
|
/* // Send another dummy byte */
|
||||||
|
/* if (n > 8) { */
|
||||||
|
/* spi_sendbyte(0xff); */
|
||||||
|
/* } */
|
||||||
|
/* // Place received byte into memory */
|
||||||
|
/* *p++ = x; */
|
||||||
|
/* // Update CRC16 with fast table based method */
|
||||||
|
/* crc = ((crc << 8) ^ crctable[x ^ (crc >> 8)]) & 0xffff; */
|
||||||
|
/* n = n - 1; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
// Read CRC16 and check
|
// Read CRC16 and check
|
||||||
crc_exp = ((uint16_t)spi_dummy() << 8);
|
crc_exp = ((uint16_t)spi_dummy() << 8);
|
||||||
|
|||||||
@ -1,4 +1,30 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
###########################################
|
||||||
|
## flash-sd.sh
|
||||||
|
##
|
||||||
|
## Written: Jacob Pease jacobpease@protonmail.com
|
||||||
|
## Created: August 22, 2023
|
||||||
|
##
|
||||||
|
## Purpose: A script to flash an sd card with a bootable linux image.
|
||||||
|
##
|
||||||
|
## A component of the CORE-V-WALLY configurable RISC-V project.
|
||||||
|
## https://github.com/openhwgroup/cvw
|
||||||
|
##
|
||||||
|
## Copyright (C) 2021-24 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.
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
# Exit on any error (return code != 0)
|
# Exit on any error (return code != 0)
|
||||||
# set -e
|
# set -e
|
||||||
|
|||||||
80
linux/sdcard/write-bytes.sh
Executable file
80
linux/sdcard/write-bytes.sh
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###########################################
|
||||||
|
## write-bytes.sh
|
||||||
|
##
|
||||||
|
## Written: Jacob Pease jacobpease@protonmail.com
|
||||||
|
## Created: November 2nd, 2024
|
||||||
|
## Modified:
|
||||||
|
##
|
||||||
|
## Purpose: Write a sequence of bytes from text file to an output file and a flash card.
|
||||||
|
##
|
||||||
|
## A component of the CORE-V-WALLY configurable RISC-V project.
|
||||||
|
## https://github.com/openhwgroup/cvw
|
||||||
|
##
|
||||||
|
## Copyright (C) 2021-24 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.
|
||||||
|
################################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# This file writes a bunch of bytes to the flash card based on a text
|
||||||
|
# file input with bytes written in hexadecimal.
|
||||||
|
|
||||||
|
usage() { echo "Usage: $0 [-zh] [-b <path/to/buildroot>] <device>" 1>&2; exit 1; }
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo "Usage: $0 [OPTIONS] <device>"
|
||||||
|
echo " -i Input text file with hex bytes."
|
||||||
|
echo " -b <path/to/buildroot> Output binary file."
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
INPUTFILE=""
|
||||||
|
OUTPUTFILE=""
|
||||||
|
|
||||||
|
ARGS=()
|
||||||
|
while [ $OPTIND -le "$#" ] ; do
|
||||||
|
if getopts "hi:o:" arg ; then
|
||||||
|
case "${arg}" in
|
||||||
|
h) help
|
||||||
|
;;
|
||||||
|
i) INPUTFILE=${OPTARG}
|
||||||
|
;;
|
||||||
|
o) OUTPUTFILE=${OPTARG}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
ARGS+=("${!OPTIND}")
|
||||||
|
((OPTIND++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
SDCARD=${ARGS[0]}
|
||||||
|
|
||||||
|
if [ ! -e $INPUTFILE ] ; then
|
||||||
|
echo -e "Error: Input file $INPUTFILE does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e $OUTPUTFILE ] ; then
|
||||||
|
echo -e "Error: Output file $OUTPUTFILE already exists."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for word in $(cat "$INPUTFILE")
|
||||||
|
do
|
||||||
|
echo -en "\x$word" >> $OUTPUTFILE
|
||||||
|
done
|
||||||
|
|
||||||
|
dd if=$OUTPUTFILE of="$SDCARD"
|
||||||
@ -181,7 +181,7 @@ if {$DEBUG > 0} {
|
|||||||
# suppress spurious warnngs about
|
# suppress spurious warnngs about
|
||||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||||
# because vsim will run vopt
|
# because vsim will run vopt
|
||||||
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
|
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/priv +incdir+${FCRVVI}/rv32_priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
|
||||||
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
||||||
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
|
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
|
||||||
|
|
||||||
|
|||||||
@ -126,7 +126,7 @@ module fround import cvw::*; #(parameter cvw_t P) (
|
|||||||
3'b001: RoundUp = 0; // RZ
|
3'b001: RoundUp = 0; // RZ
|
||||||
3'b010: RoundUp = Xs & (Rp | Tp); // RN
|
3'b010: RoundUp = Xs & (Rp | Tp); // RN
|
||||||
3'b011: RoundUp = ~Xs & (Rp | Tp); // RP
|
3'b011: RoundUp = ~Xs & (Rp | Tp); // RP
|
||||||
3'b101: RoundUp = Rp; // RNTA
|
3'b100: RoundUp = Rp; // RNTA
|
||||||
default: RoundUp = 0; // should never happen
|
default: RoundUp = 0; // should never happen
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// spi_apb.sv
|
// spi_apb.sv
|
||||||
//
|
//
|
||||||
// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu 11/16/2022
|
// Written: Naiche Whyte-Aguayo nwhyteaguayo@g.hmc.edu
|
||||||
|
// Jacob Pease jacobpease@protonmail.com (October 29th, 2024)
|
||||||
|
// Created: November 16th, 2022
|
||||||
//
|
//
|
||||||
// Purpose: SPI peripheral
|
// Purpose: SPI peripheral
|
||||||
//
|
//
|
||||||
@ -13,7 +15,7 @@
|
|||||||
//
|
//
|
||||||
// A component of the Wally configurable RISC-V project.
|
// A component of the Wally configurable RISC-V project.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||||
//
|
//
|
||||||
@ -62,10 +64,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam SPI_IE = 8'h70;
|
localparam SPI_IE = 8'h70;
|
||||||
localparam SPI_IP = 8'h74;
|
localparam SPI_IP = 8'h74;
|
||||||
|
|
||||||
// receive shift register states
|
|
||||||
typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} rsrstatetype;
|
|
||||||
|
|
||||||
|
|
||||||
// SPI control registers. Refer to SiFive FU540-C000 manual
|
// SPI control registers. Refer to SiFive FU540-C000 manual
|
||||||
logic [11:0] SckDiv;
|
logic [11:0] SckDiv;
|
||||||
logic [1:0] SckMode;
|
logic [1:0] SckMode;
|
||||||
@ -75,89 +73,70 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [15:0] Delay0, Delay1;
|
logic [15:0] Delay0, Delay1;
|
||||||
logic [4:0] Format;
|
logic [4:0] Format;
|
||||||
logic [7:0] ReceiveData;
|
logic [7:0] ReceiveData;
|
||||||
logic [2:0] TransmitWatermark, ReceiveWatermark;
|
|
||||||
logic [8:0] TransmitData;
|
logic [8:0] TransmitData;
|
||||||
|
logic [2:0] TransmitWatermark, ReceiveWatermark;
|
||||||
logic [1:0] InterruptEnable, InterruptPending;
|
logic [1:0] InterruptEnable, InterruptPending;
|
||||||
|
|
||||||
// Bus interface signals
|
// Bus interface signals
|
||||||
logic [7:0] Entry;
|
logic [7:0] Entry;
|
||||||
logic Memwrite;
|
logic Memwrite;
|
||||||
logic [31:0] Din, Dout;
|
logic [31:0] Din, Dout;
|
||||||
logic TransmitInactive; // High when there is no transmission, used as hardware interlock signal
|
|
||||||
|
// SPI Controller signals
|
||||||
|
logic SCLKenable;
|
||||||
|
logic EndOfFrame;
|
||||||
|
logic EndOfFrameDelay;
|
||||||
|
logic Transmitting;
|
||||||
|
logic InactiveState;
|
||||||
|
logic [3:0] FrameLength;
|
||||||
|
|
||||||
|
logic ResetSCLKenable;
|
||||||
|
logic TransmitStart;
|
||||||
|
logic TransmitStartD;
|
||||||
|
|
||||||
|
// Transmit Start State Machine Variables
|
||||||
|
typedef enum logic [1:0] {READY, START, WAIT} txState;
|
||||||
|
txState CurrState, NextState;
|
||||||
|
|
||||||
// FIFO FSM signals
|
// FIFO FSM signals
|
||||||
// Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
|
// Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
|
||||||
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark;
|
||||||
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty;
|
||||||
logic TransmitFIFOWriteIncrement;
|
logic TransmitFIFOWriteIncrement;
|
||||||
logic ReceiveFiFoWriteInc;
|
logic [7:0] TransmitFIFOReadData;
|
||||||
|
|
||||||
|
logic ReceiveFIFOWriteInc;
|
||||||
logic ReceiveFIFOReadIncrement;
|
logic ReceiveFIFOReadIncrement;
|
||||||
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
||||||
logic [7:0] TransmitFIFOReadData;
|
|
||||||
/* verilator lint_off UNDRIVEN */
|
/* verilator lint_off UNDRIVEN */
|
||||||
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs
|
logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs
|
||||||
/* verilator lint_off UNDRIVEN */
|
/* verilator lint_off UNDRIVEN */
|
||||||
logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission)
|
logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission)
|
||||||
rsrstatetype ReceiveState;
|
|
||||||
logic ReceiveFiFoTakingData;
|
|
||||||
|
|
||||||
// Transmission signals
|
|
||||||
logic ZeroDiv; // High when SckDiv is 0
|
|
||||||
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 ZeroDelayHoldMode; // High when ChipSelectMode is hold and Delay1[15:8] (InterXFR delay) is 0
|
|
||||||
|
|
||||||
// Frame counting signals
|
|
||||||
logic FirstFrame;
|
|
||||||
logic [3:0] FrameCount; // Counter for number of frames in transmission
|
|
||||||
logic ReceivePenultimateFrame; // 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
|
// Shift reg signals
|
||||||
logic ShiftEdge; // Determines which edge of sck to shift from TransmitShiftReg
|
logic ShiftEdge; // Determines which edge of sck to shift from TransmitReg
|
||||||
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 SampleEdge; // Determines which edge of sck to sample from ReceiveShiftReg
|
||||||
|
logic [7:0] TransmitReg; // Transmit shift register
|
||||||
|
logic [7:0] ReceiveShiftReg; // Receive shift register
|
||||||
logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
|
logic [7:0] TransmitDataEndian; // Reverses TransmitData from txFIFO if littleendian, since TransmitReg always shifts MSB
|
||||||
logic TransmitShiftRegLoad; // Determines when to load TransmitShiftReg
|
logic TransmitLoad; // Determines when to load TransmitReg
|
||||||
logic TransmitShiftRegLoadSingleCycle; // Version of TransmitShiftRegLoad which is only high for a single SCLK cycle to prevent double loads
|
|
||||||
logic TransmitShiftRegLoadDelay; // TransmitShiftRegLoad delayed by an SCLK cycle, inverted and anded with TransmitShiftRegLoad to create a single cycle signal
|
|
||||||
logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read
|
logic TransmitFIFOReadIncrement; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read
|
||||||
logic ReceiveShiftFull; // High when receive shift register is full
|
|
||||||
logic TransmitShiftEmpty; // High when transmit shift register is empty
|
// Shift stuff due to Format register?
|
||||||
logic ShiftIn; // Determines whether to shift from SPIIn or SPIOut (if SPI_LOOPBACK_TEST)
|
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 [3:0] LeftShiftAmount; // Determines left shift amount to left-align data when little endian
|
||||||
logic [7:0] ASR; // AlignedReceiveShiftReg
|
logic [7:0] ASR; // AlignedReceiveShiftReg
|
||||||
logic ShiftEdgeSPICLK; // Changes ShiftEdge when SckDiv is 0
|
|
||||||
|
|
||||||
// CS signals
|
// CS signals
|
||||||
logic [3:0] ChipSelectAuto; // Assigns ChipSelect value to selected CS signal based on CS ID
|
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 [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 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
|
// APB access
|
||||||
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
|
||||||
assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase
|
assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase
|
||||||
assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP | TransmitInactive; // Tie PREADY to transmission for hardware interlock
|
// assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP;
|
||||||
|
assign PREADY = 1'b1;
|
||||||
|
|
||||||
// Account for subword read/write circuitry
|
// Account for subword read/write circuitry
|
||||||
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
|
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
|
||||||
@ -183,10 +162,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
InterruptEnable <= 2'b0;
|
InterruptEnable <= 2'b0;
|
||||||
InterruptPending <= 2'b0;
|
InterruptPending <= 2'b0;
|
||||||
end else begin // writes
|
end else begin // writes
|
||||||
|
|
||||||
|
|
||||||
/* verilator lint_off CASEINCOMPLETE */
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
if (Memwrite & TransmitInactive)
|
if (Memwrite)
|
||||||
case(Entry) // flop to sample inputs
|
case(Entry) // flop to sample inputs
|
||||||
SPI_SCKDIV: SckDiv <= Din[11:0];
|
SPI_SCKDIV: SckDiv <= Din[11:0];
|
||||||
SPI_SCKMODE: SckMode <= Din[1:0];
|
SPI_SCKMODE: SckMode <= Din[1:0];
|
||||||
@ -234,227 +211,151 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
// SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
// SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1))
|
||||||
// Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
// Asserts SCLKenable at the rising and falling edge of SCLK by counting from 0 to SckDiv
|
||||||
// Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase
|
// Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase
|
||||||
// When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)). SCLKenableEarly doesn't work right for SckDiv=0
|
// When SckDiv is 0, count doesn't work and SCLKenable is simply PCLK *** dh 10/26/24: this logic is seriously broken. SCLK is not scaled to PCLK/(2*(SckDiv + 1)).
|
||||||
assign ZeroDiv = ~|(SckDiv[10:0]);
|
|
||||||
assign SCLKenable = ZeroDiv ? 1 : (DivCounter == SckDiv);
|
// SPI Controller module -------------------------------------------
|
||||||
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
// This module controls state and timing signals that drive the rest of this module
|
||||||
|
assign ResetSCLKenable = Memwrite & (Entry == SPI_SCKDIV);
|
||||||
|
assign FrameLength = Format[4:1];
|
||||||
|
|
||||||
|
spi_controller controller(PCLK, PRESETn,
|
||||||
|
// Transmit Signals
|
||||||
|
TransmitStart, TransmitStartD, ResetSCLKenable,
|
||||||
|
// Register Inputs
|
||||||
|
SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength,
|
||||||
|
// txFIFO stuff
|
||||||
|
TransmitFIFOReadEmpty,
|
||||||
|
// Timing
|
||||||
|
SCLKenable, ShiftEdge, SampleEdge, EndOfFrame, EndOfFrameDelay,
|
||||||
|
// State stuff
|
||||||
|
Transmitting, InactiveState,
|
||||||
|
// Outputs
|
||||||
|
SPICLK);
|
||||||
|
|
||||||
|
// Transmit FIFO ---------------------------------------------------
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) DivCounter <= '0;
|
if (~PRESETn) begin
|
||||||
else if (SCLKenable) DivCounter <= 12'b0;
|
TransmitFIFOWriteIncrement <= 1'b0;
|
||||||
else DivCounter <= DivCounter + 12'b1;
|
|
||||||
|
|
||||||
// Asserts when transmission is one frame before complete
|
|
||||||
assign ReceivePenultimateFrame = ((FrameCount + 4'b0001) == Format[4:1]);
|
|
||||||
assign FirstFrame = (FrameCount == 4'b0);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Calculate when tx/rx shift registers are full/empty
|
|
||||||
|
|
||||||
// Transmit Shift FSM
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) TransmitShiftEmpty <= 1'b1;
|
|
||||||
else if (TransmitShiftEmpty) begin
|
|
||||||
if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrame & Active0))) TransmitShiftEmpty <= 1'b1;
|
|
||||||
else if (~TransmitFIFOReadEmpty) TransmitShiftEmpty <= 1'b0;
|
|
||||||
end else begin
|
end else begin
|
||||||
if (ReceivePenultimateFrame & Active0) TransmitShiftEmpty <= 1'b1;
|
TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull);
|
||||||
else TransmitShiftEmpty <= 1'b0;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Receive Shift FSM
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState;
|
|
||||||
else if (SCLKenable) begin
|
|
||||||
case (ReceiveState)
|
|
||||||
ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState;
|
|
||||||
ReceiveShiftNotFullState: if (ReceivePenultimateFrame & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState;
|
|
||||||
else ReceiveState <= ReceiveShiftNotFullState;
|
|
||||||
ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
assign ReceiveShiftFull = SckMode[0] ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState);
|
|
||||||
|
|
||||||
// Calculate tx/rx fifo write and recieve increment signals
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0;
|
|
||||||
else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull);
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0;
|
|
||||||
else ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
|
||||||
|
|
||||||
assign TransmitShiftRegLoad = ~TransmitShiftEmpty & ~Active | (((ChipSelectMode == 2'b10) & ~|(Delay1[15:8])) & ((ReceiveShiftFullDelay | ReceiveShiftFull) & ~SampleEdge & ~TransmitFIFOReadEmpty));
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) TransmitShiftRegLoadDelay <=0;
|
|
||||||
else if (SCLKenable) TransmitShiftRegLoadDelay <= TransmitShiftRegLoad;
|
|
||||||
assign TransmitShiftRegLoadSingleCycle = TransmitShiftRegLoad & ~TransmitShiftRegLoadDelay;
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) TransmitFIFOReadIncrement <= 0;
|
|
||||||
else if (SCLKenable) TransmitFIFOReadIncrement <= TransmitShiftRegLoadSingleCycle;
|
|
||||||
// Tx/Rx FIFOs
|
|
||||||
spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0],
|
|
||||||
TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark);
|
|
||||||
spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveFiFoWriteInc, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel,
|
|
||||||
ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1'b1;
|
|
||||||
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) ReceiveShiftFullDelay <= 1'b0;
|
|
||||||
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
|
|
||||||
|
|
||||||
assign ReceiveFiFoTakingData = ReceiveFiFoWriteInc & ~ReceiveFIFOWriteFull;
|
|
||||||
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) ReceiveFiFoWriteInc <= 1'b0;
|
|
||||||
else if (SCLKenable & ReceiveShiftFull) ReceiveFiFoWriteInc <= 1'b1;
|
|
||||||
else if (SCLKenable & ReceiveFiFoTakingData) ReceiveFiFoWriteInc <= 1'b0;
|
|
||||||
always_ff @(posedge PCLK)
|
|
||||||
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0;
|
|
||||||
else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
state <= CS_INACTIVE;
|
TransmitFIFOReadIncrement <= 1'b0;
|
||||||
FrameCount <= 4'b0;
|
|
||||||
SPICLK <= SckMode[1];
|
|
||||||
end else if (SCLKenable) begin
|
end else if (SCLKenable) begin
|
||||||
/* verilator lint_off CASEINCOMPLETE */
|
TransmitFIFOReadIncrement <= TransmitStartD | (EndOfFrameDelay & ~TransmitFIFOReadEmpty) ;
|
||||||
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)) begin
|
|
||||||
state <= ACTIVE_0;
|
|
||||||
SPICLK <= ~SckMode[1];
|
|
||||||
end else SPICLK <= SckMode[1];
|
|
||||||
end
|
end
|
||||||
DELAY_0: begin
|
|
||||||
CS_SCKCount <= CS_SCKCount + 9'b1;
|
// Check whether TransmitReg has been loaded.
|
||||||
if (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1)) begin
|
// We use this signal to prevent returning to the Ready state for TransmitStart
|
||||||
state <= ACTIVE_0;
|
logic TransmitRegLoaded;
|
||||||
SPICLK <= ~SckMode[1];
|
always_ff @(posedge PCLK) begin
|
||||||
|
if (~PRESETn) begin
|
||||||
|
TransmitRegLoaded <= 1'b0;
|
||||||
|
end else if (TransmitLoad) begin
|
||||||
|
TransmitRegLoaded <= 1'b1;
|
||||||
|
end else if (ShiftEdge | EndOfFrameDelay) begin
|
||||||
|
TransmitRegLoaded <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ACTIVE_0: begin
|
|
||||||
FrameCount <= FrameCount + 4'b1;
|
// Setup TransmitStart state machine
|
||||||
SPICLK <= SckMode[1];
|
always_ff @(posedge PCLK) begin
|
||||||
state <= ACTIVE_1;
|
if (~PRESETn) begin
|
||||||
|
CurrState <= READY;
|
||||||
|
end else begin
|
||||||
|
CurrState <= NextState;
|
||||||
end
|
end
|
||||||
ACTIVE_1: begin
|
|
||||||
InterXFRCount <= 9'b1;
|
|
||||||
if (FrameCount < Format[4:1]) begin
|
|
||||||
state <= ACTIVE_0;
|
|
||||||
SPICLK <= ~SckMode[1];
|
|
||||||
end
|
|
||||||
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
|
|
||||||
state <= ACTIVE_0;
|
|
||||||
SPICLK <= ~SckMode[1];
|
|
||||||
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_CSCount >= (({Delay0[15:8], 1'b0}) + ImplicitDelay2)) state <= INTER_CS;
|
|
||||||
end
|
|
||||||
INTER_CS: begin
|
|
||||||
InterCSCount <= InterCSCount + 9'b1;
|
|
||||||
SPICLK <= SckMode[1];
|
|
||||||
if (InterCSCount >= ({Delay1[7:0],1'b0})) 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 ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & (~TransmitFIFOReadEmptyDelay | ~TransmitShiftEmpty)) begin
|
|
||||||
state <= ACTIVE_0;
|
|
||||||
SPICLK <= ~SckMode[1];
|
|
||||||
end else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
|
|
||||||
else SPICLK <= SckMode[1];
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// State machine for starting transmissions
|
||||||
|
always_comb begin
|
||||||
|
case (CurrState)
|
||||||
|
READY: if (~TransmitFIFOReadEmpty & ~Transmitting) NextState = START;
|
||||||
|
else NextState = READY;
|
||||||
|
START: NextState = WAIT;
|
||||||
|
WAIT: if (~Transmitting & ~TransmitRegLoaded) NextState = READY;
|
||||||
|
else NextState = WAIT;
|
||||||
|
default: NextState = READY;
|
||||||
endcase
|
endcase
|
||||||
/* verilator lint_off CASEINCOMPLETE */
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assign TransmitStart = (CurrState == START);
|
||||||
|
always_ff @(posedge PCLK)
|
||||||
|
if (~PRESETn) TransmitStartD <= 1'b0;
|
||||||
|
else if (TransmitStart) TransmitStartD <= 1'b1;
|
||||||
|
else if (SCLKenable) TransmitStartD <= 1'b0;
|
||||||
|
|
||||||
|
spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn,
|
||||||
|
TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement,
|
||||||
|
TransmitData[7:0],
|
||||||
|
TransmitWriteWatermarkLevel, TransmitWatermark[2:0],
|
||||||
|
TransmitFIFOReadData[7:0],
|
||||||
|
TransmitFIFOWriteFull,
|
||||||
|
TransmitFIFOReadEmpty,
|
||||||
|
TransmitWriteMark, TransmitReadMark);
|
||||||
|
|
||||||
|
|
||||||
assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
|
// Receive FIFO ----------------------------------------------------
|
||||||
assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
|
always_ff @(posedge PCLK)
|
||||||
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
|
if (~PRESETn) begin
|
||||||
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
|
ReceiveFIFOReadIncrement <= 1'b0;
|
||||||
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
|
end else begin
|
||||||
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode) | ((state == ACTIVE_1) & ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & (FrameCount == Format[4:1]))));
|
ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||||
assign Active0 = (state == ACTIVE_0);
|
end
|
||||||
assign ShiftEdgeSPICLK = ZeroDiv ? ~SPICLK : SPICLK;
|
|
||||||
|
|
||||||
// Signal tracks which edge of sck to shift data
|
always_ff @(posedge PCLK)
|
||||||
always_comb
|
if (~PRESETn) begin
|
||||||
case(SckMode[1:0])
|
ReceiveFIFOWriteInc <= 1'b0;
|
||||||
2'b00: ShiftEdge = ShiftEdgeSPICLK & SCLKenable;
|
end else if (SCLKenable) begin
|
||||||
2'b01: ShiftEdge = (~ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive);
|
ReceiveFIFOWriteInc <= EndOfFrameDelay;
|
||||||
2'b10: ShiftEdge = ~ShiftEdgeSPICLK & SCLKenable;
|
end
|
||||||
2'b11: ShiftEdge = (ShiftEdgeSPICLK & ~FirstFrame & (|(FrameCount) | (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1))) & SCLKenable & (FrameCount != Format[4:1]) & ~TransmitInactive);
|
|
||||||
default: ShiftEdge = ShiftEdgeSPICLK & SCLKenable;
|
spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn,
|
||||||
endcase
|
ReceiveFIFOWriteInc, ReceiveFIFOReadIncrement,
|
||||||
|
ReceiveShiftRegEndian, ReceiveWatermark[2:0],
|
||||||
|
ReceiveReadWatermarkLevel,
|
||||||
|
ReceiveData[7:0],
|
||||||
|
ReceiveFIFOWriteFull,
|
||||||
|
ReceiveFIFOReadEmpty,
|
||||||
|
RecieveWriteMark, RecieveReadMark);
|
||||||
|
|
||||||
// Transmit shift register
|
// 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];
|
assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~TransmitFIFOReadEmpty);
|
||||||
|
assign TransmitDataEndian = Format[0] ? {<<{TransmitFIFOReadData[7:0]}} : TransmitFIFOReadData[7:0];
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
if(~PRESETn) TransmitShiftReg <= 8'b0;
|
if(~PRESETn) TransmitReg <= 8'b0;
|
||||||
else if (TransmitShiftRegLoadSingleCycle) TransmitShiftReg <= TransmitDataEndian;
|
else if (TransmitLoad) TransmitReg <= TransmitDataEndian;
|
||||||
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], TransmitShiftReg[0]};
|
else if (ShiftEdge) TransmitReg <= {TransmitReg[6:0], TransmitReg[0]};
|
||||||
|
|
||||||
assign SPIOut = TransmitShiftReg[7];
|
assign SPIOut = TransmitReg[7];
|
||||||
|
|
||||||
// If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn
|
// If in loopback mode, receive shift register is connected directly
|
||||||
// There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges
|
// 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;
|
assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
|
||||||
|
|
||||||
// Receive shift register
|
// Receive shift register
|
||||||
always_ff @(posedge PCLK)
|
always_ff @(posedge PCLK)
|
||||||
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
if(~PRESETn) begin
|
||||||
else if (SampleEdge & SCLKenable) begin
|
ReceiveShiftReg <= 8'b0;
|
||||||
if (~Active) ReceiveShiftReg <= 8'b0;
|
end else if (SampleEdge) begin
|
||||||
|
if (~Transmitting) ReceiveShiftReg <= 8'b0;
|
||||||
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
|
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
|
||||||
end
|
end
|
||||||
|
|
||||||
// Aligns received data and reverses if little-endian
|
// Aligns received data and reverses if little-endian
|
||||||
assign LeftShiftAmount = 4'h8 - Format[4:1];
|
assign LeftShiftAmount = 4'h8 - Format[4:1];
|
||||||
assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
|
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];
|
assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0];
|
||||||
|
|
||||||
// Interrupt logic: raise interrupt if any enabled interrupts are pending
|
// Interrupt logic: raise interrupt if any enabled interrupts are pending
|
||||||
assign SPIIntr = |(InterruptPending & InterruptEnable);
|
assign SPIIntr = |(InterruptPending & InterruptEnable);
|
||||||
|
|
||||||
// Chip select logic
|
// Chip select logic
|
||||||
|
assign ChipSelectInternal = InactiveState ? ChipSelectDef : ~ChipSelectDef;
|
||||||
always_comb
|
always_comb
|
||||||
case(ChipSelectID[1:0])
|
case(ChipSelectID[1:0])
|
||||||
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
|
2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]};
|
||||||
@ -462,6 +363,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[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]};
|
2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]};
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
|
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// spi_controller.sv
|
// spi_controller.sv
|
||||||
//
|
//
|
||||||
// Written: jacobpease@protonmail.com
|
// Written: Jacob Pease jacobpease@protonmail.com
|
||||||
// Created: October 28th, 2024
|
// Created: October 28th, 2024
|
||||||
// Modified:
|
|
||||||
//
|
//
|
||||||
// Purpose: Controller logic for SPI
|
// Purpose: Controller logic for SPI
|
||||||
//
|
//
|
||||||
@ -12,7 +11,7 @@
|
|||||||
// A component of the CORE-V-WALLY configurable RISC-V project.
|
// A component of the CORE-V-WALLY configurable RISC-V project.
|
||||||
// https://github.com/openhwgroup/cvw
|
// https://github.com/openhwgroup/cvw
|
||||||
//
|
//
|
||||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
// Copyright (C) 2021-24 Harvey Mudd College & Oklahoma State University
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||||
//
|
//
|
||||||
@ -28,21 +27,35 @@
|
|||||||
// and limitations under the License.
|
// and limitations under the License.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
module spi_controller (
|
module spi_controller (
|
||||||
input logic PCLK,
|
input logic PCLK,
|
||||||
input logic PRESETn,
|
input logic PRESETn,
|
||||||
|
|
||||||
|
// Start Transmission
|
||||||
input logic TransmitStart,
|
input logic TransmitStart,
|
||||||
|
input logic TransmitStartD,
|
||||||
|
input logic ResetSCLKenable,
|
||||||
|
|
||||||
|
// Registers
|
||||||
input logic [11:0] SckDiv,
|
input logic [11:0] SckDiv,
|
||||||
input logic [1:0] SckMode,
|
input logic [1:0] SckMode,
|
||||||
input logic [1:0] CSMode,
|
input logic [1:0] CSMode,
|
||||||
input logic [15:0] Delay0,
|
input logic [15:0] Delay0,
|
||||||
input logic [15:0] Delay1,
|
input logic [15:0] Delay1,
|
||||||
input logic [7:0] txFIFORead,
|
input logic [3:0] FrameLength,
|
||||||
|
|
||||||
|
// Is the Transmit FIFO Empty?
|
||||||
input logic txFIFOReadEmpty,
|
input logic txFIFOReadEmpty,
|
||||||
output logic SPICLK,
|
|
||||||
output logic SPIOUT,
|
// Control signals
|
||||||
output logic CS
|
output logic SCLKenable,
|
||||||
|
output logic ShiftEdge,
|
||||||
|
output logic SampleEdge,
|
||||||
|
output logic EndOfFrame,
|
||||||
|
output logic EndOfFrameDelay,
|
||||||
|
output logic Transmitting,
|
||||||
|
output logic InactiveState,
|
||||||
|
output logic SPICLK
|
||||||
);
|
);
|
||||||
|
|
||||||
// CSMode Stuff
|
// CSMode Stuff
|
||||||
@ -55,36 +68,35 @@ module spi_controller (
|
|||||||
|
|
||||||
// SCLKenable stuff
|
// SCLKenable stuff
|
||||||
logic [11:0] DivCounter;
|
logic [11:0] DivCounter;
|
||||||
logic SCLKenable;
|
// logic SCLKenable;
|
||||||
logic SCLKenableEarly;
|
// logic SCLKenableEarly;
|
||||||
logic SCLKenableLate;
|
|
||||||
logic EdgeTiming;
|
|
||||||
logic ZeroDiv;
|
logic ZeroDiv;
|
||||||
logic Clock0;
|
|
||||||
logic Clock1;
|
|
||||||
logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK!
|
logic SCK; // SUPER IMPORTANT, THIS CAN'T BE THE SAME AS SPICLK!
|
||||||
|
|
||||||
|
|
||||||
// Shift and Sample Edges
|
// Shift and Sample Edges
|
||||||
logic PreShiftEdge;
|
logic PreShiftEdge;
|
||||||
logic PreSampleEdge;
|
logic PreSampleEdge;
|
||||||
logic ShiftEdge;
|
// logic ShiftEdge;
|
||||||
logic SampleEdge;
|
// logic SampleEdge;
|
||||||
|
logic ShiftEdgePulse;
|
||||||
|
logic SampleEdgePulse;
|
||||||
|
logic EndOfFramePulse;
|
||||||
|
|
||||||
// Frame stuff
|
// Frame stuff
|
||||||
logic [2:0] BitNum;
|
logic [3:0] BitNum;
|
||||||
logic LastBit;
|
logic LastBit;
|
||||||
logic EndOfFrame;
|
//logic EndOfFrame;
|
||||||
logic EndOfFrameDelay;
|
//logic EndOfFrameDelay;
|
||||||
logic PhaseOneOffset;
|
logic PhaseOneOffset;
|
||||||
|
|
||||||
// Transmit Stuff
|
// Transmit Stuff
|
||||||
logic ContinueTransmit;
|
logic ContinueTransmit;
|
||||||
|
|
||||||
// SPIOUT Stuff
|
// SPIOUT Stuff
|
||||||
logic TransmitLoad;
|
// logic TransmitLoad;
|
||||||
logic [7:0] TransmitReg;
|
logic [7:0] TransmitReg;
|
||||||
logic Transmitting;
|
//logic Transmitting;
|
||||||
logic EndTransmission;
|
logic EndTransmission;
|
||||||
|
|
||||||
logic HoldMode;
|
logic HoldMode;
|
||||||
@ -135,15 +147,12 @@ module spi_controller (
|
|||||||
// SampleEdge. This makes sure that SPICLK is an output of a register
|
// SampleEdge. This makes sure that SPICLK is an output of a register
|
||||||
// and it properly synchronizes signals.
|
// and it properly synchronizes signals.
|
||||||
|
|
||||||
assign SCLKenableLate = DivCounter > SckDiv;
|
|
||||||
assign SCLKenable = DivCounter == SckDiv;
|
assign SCLKenable = DivCounter == SckDiv;
|
||||||
assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv;
|
// assign SCLKenableEarly = (DivCounter + 1'b1) == SckDiv;
|
||||||
assign LastBit = BitNum == 3'd7;
|
assign LastBit = (BitNum == FrameLength - 4'b1);
|
||||||
assign EdgeTiming = SckDiv > 12'b0 ? SCLKenableEarly : SCLKenable;
|
|
||||||
|
|
||||||
//assign SPICLK = Clock0;
|
//assign EndOfFrame = SCLKenable & LastBit & Transmitting;
|
||||||
|
assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrameDelay;
|
||||||
assign ContinueTransmit = ~txFIFOReadEmpty & EndOfFrame;
|
|
||||||
assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay;
|
assign EndTransmission = txFIFOReadEmpty & EndOfFrameDelay;
|
||||||
|
|
||||||
always_ff @(posedge PCLK) begin
|
always_ff @(posedge PCLK) begin
|
||||||
@ -151,10 +160,14 @@ module spi_controller (
|
|||||||
DivCounter <= 12'b0;
|
DivCounter <= 12'b0;
|
||||||
SPICLK <= SckMode[1];
|
SPICLK <= SckMode[1];
|
||||||
SCK <= 0;
|
SCK <= 0;
|
||||||
BitNum <= 3'h0;
|
BitNum <= 4'h0;
|
||||||
PreShiftEdge <= 0;
|
PreShiftEdge <= 0;
|
||||||
PreSampleEdge <= 0;
|
PreSampleEdge <= 0;
|
||||||
EndOfFrame <= 0;
|
EndOfFrame <= 0;
|
||||||
|
CSSCKCounter <= 0;
|
||||||
|
SCKCSCounter <= 0;
|
||||||
|
INTERCSCounter <= 0;
|
||||||
|
INTERXFRCounter <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
// TODO: Consolidate into one delay counter since none of the
|
// TODO: Consolidate into one delay counter since none of the
|
||||||
// delays happen at the same time?
|
// delays happen at the same time?
|
||||||
@ -164,27 +177,27 @@ module spi_controller (
|
|||||||
SCK <= ~SCK;
|
SCK <= ~SCK;
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((CurrState == CSSCK) & SCK) begin
|
if ((CurrState == CSSCK) & SCK & SCLKenable) begin
|
||||||
CSSCKCounter <= CSSCKCounter + 8'd1;
|
CSSCKCounter <= CSSCKCounter + 8'd1;
|
||||||
end else begin
|
end else if (SCLKenable & EndOfCSSCK) begin
|
||||||
CSSCKCounter <= 8'd0;
|
CSSCKCounter <= 8'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((CurrState == SCKCS) & SCK) begin
|
if ((CurrState == SCKCS) & SCK & SCLKenable) begin
|
||||||
SCKCSCounter <= SCKCSCounter + 8'd1;
|
SCKCSCounter <= SCKCSCounter + 8'd1;
|
||||||
end else begin
|
end else if (SCLKenable & EndOfSCKCS) begin
|
||||||
SCKCSCounter <= 8'd0;
|
SCKCSCounter <= 8'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((CurrState == INTERCS) & SCK) begin
|
if ((CurrState == INTERCS) & SCK & SCLKenable) begin
|
||||||
INTERCSCounter <= INTERCSCounter + 8'd1;
|
INTERCSCounter <= INTERCSCounter + 8'd1;
|
||||||
end else begin
|
end else if (SCLKenable & EndOfINTERCS) begin
|
||||||
INTERCSCounter <= 8'd0;
|
INTERCSCounter <= 8'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((CurrState == INTERXFR) & SCK) begin
|
if ((CurrState == INTERXFR) & SCK & SCLKenable) begin
|
||||||
INTERXFRCounter <= INTERXFRCounter + 8'd1;
|
INTERXFRCounter <= INTERXFRCounter + 8'd1;
|
||||||
end else begin
|
end else if (SCLKenable & EndOfINTERXFR) begin
|
||||||
INTERXFRCounter <= 8'd0;
|
INTERXFRCounter <= 8'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -196,10 +209,10 @@ module spi_controller (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Reset divider
|
// Reset divider
|
||||||
if (SCLKenable | TransmitStart) begin
|
if (SCLKenable | TransmitStart | ResetSCLKenable) begin
|
||||||
DivCounter <= 12'b0;
|
DivCounter <= 12'b0;
|
||||||
end else begin
|
end else begin
|
||||||
DivCounter = DivCounter + 12'd1;
|
DivCounter <= DivCounter + 12'd1;
|
||||||
end
|
end
|
||||||
|
|
||||||
// EndOfFrame controller
|
// EndOfFrame controller
|
||||||
@ -209,15 +222,16 @@ module spi_controller (
|
|||||||
// EndOfFrame <= 1'b0;
|
// EndOfFrame <= 1'b0;
|
||||||
// end
|
// end
|
||||||
|
|
||||||
|
// TODO: Rename EndOfFrameDelay to EndOfFrame and remove this logic
|
||||||
if (~TransmitStart) begin
|
if (~TransmitStart) begin
|
||||||
EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
|
EndOfFrame <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
|
||||||
end
|
end
|
||||||
|
|
||||||
// Increment BitNum
|
// Increment BitNum
|
||||||
if (ShiftEdge & Transmitting) begin
|
if (ShiftEdge & Transmitting) begin
|
||||||
BitNum <= BitNum + 3'd1;
|
BitNum <= BitNum + 4'd1;
|
||||||
end else if (EndOfFrameDelay) begin
|
end else if (EndOfFrameDelay) begin
|
||||||
BitNum <= 3'b0;
|
BitNum <= 4'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -225,6 +239,11 @@ module spi_controller (
|
|||||||
// Delay ShiftEdge and SampleEdge by a half PCLK period
|
// Delay ShiftEdge and SampleEdge by a half PCLK period
|
||||||
// Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges.
|
// Aligned EXACTLY ON THE MIDDLE of the leading and trailing edges.
|
||||||
// Sweeeeeeeeeet...
|
// Sweeeeeeeeeet...
|
||||||
|
|
||||||
|
assign ShiftEdgePulse = SCLKenable & ~LastBit & Transmitting;
|
||||||
|
assign SampleEdgePulse = SCLKenable & Transmitting & ~DelayIsNext;
|
||||||
|
assign EndOfFramePulse = SCLKenable & LastBit & Transmitting;
|
||||||
|
|
||||||
always_ff @(posedge ~PCLK) begin
|
always_ff @(posedge ~PCLK) begin
|
||||||
if (~PRESETn | TransmitStart) begin
|
if (~PRESETn | TransmitStart) begin
|
||||||
ShiftEdge <= 0;
|
ShiftEdge <= 0;
|
||||||
@ -232,18 +251,58 @@ module spi_controller (
|
|||||||
SampleEdge <= 0;
|
SampleEdge <= 0;
|
||||||
EndOfFrameDelay <= 0;
|
EndOfFrameDelay <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset;
|
PhaseOneOffset <= (PhaseOneOffset == 0) ? Transmitting & SCLKenable : ~EndOfFrameDelay;
|
||||||
PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : PhaseOneOffset;
|
case(SckMode)
|
||||||
SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting;
|
2'b00: begin
|
||||||
EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
|
ShiftEdge <= SPICLK & ShiftEdgePulse;
|
||||||
|
SampleEdge <= ~SPICLK & SampleEdgePulse;
|
||||||
|
EndOfFrameDelay <= SPICLK & EndOfFramePulse;
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
ShiftEdge <= ~SPICLK & ShiftEdgePulse & PhaseOneOffset;
|
||||||
|
SampleEdge <= SPICLK & SampleEdgePulse;
|
||||||
|
EndOfFrameDelay <= ~SPICLK & EndOfFramePulse;
|
||||||
|
end
|
||||||
|
2'b10: begin
|
||||||
|
ShiftEdge <= ~SPICLK & ShiftEdgePulse;
|
||||||
|
SampleEdge <= SPICLK & SampleEdgePulse;
|
||||||
|
EndOfFrameDelay <= ~SPICLK & EndOfFramePulse;
|
||||||
|
end
|
||||||
|
2'b11: begin
|
||||||
|
ShiftEdge <= SPICLK & ShiftEdgePulse & PhaseOneOffset;
|
||||||
|
SampleEdge <= ~SPICLK & SampleEdgePulse;
|
||||||
|
EndOfFrameDelay <= SPICLK & EndOfFramePulse;
|
||||||
|
end
|
||||||
|
// ShiftEdge <= ((SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & ~LastBit & Transmitting) & PhaseOneOffset;
|
||||||
|
// PhaseOneOffset <= PhaseOneOffset == 0 ? Transmitting & SCLKenable : ~EndOfFrameDelay;
|
||||||
|
// SampleEdge <= (SckMode[1] ^ SckMode[0] ^ ~SPICLK) & SCLKenable & Transmitting & ~DelayIsNext;
|
||||||
|
// EndOfFrameDelay <= (SckMode[1] ^ SckMode[0] ^ SPICLK) & SCLKenable & LastBit & Transmitting;
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype;
|
// typedef enum logic [2:0] {INACTIVE, CSSCK, TRANSMIT, SCKCS, HOLD, INTERCS, INTERXFR} statetype;
|
||||||
// statetype CurrState, NextState;
|
// statetype CurrState, NextState;
|
||||||
|
|
||||||
assign HoldMode = CSMode == 2'b10;
|
assign HoldMode = CSMode == HOLDMODE;
|
||||||
assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty);
|
// assign TransmitLoad = TransmitStart | (EndOfFrameDelay & ~txFIFOReadEmpty);
|
||||||
|
|
||||||
|
logic ContinueTransmitD;
|
||||||
|
logic NextEndDelay;
|
||||||
|
logic CurrentEndDelay;
|
||||||
|
|
||||||
|
assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR;
|
||||||
|
assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR;
|
||||||
|
|
||||||
|
always_ff @(posedge PCLK) begin
|
||||||
|
if (~PRESETn) begin
|
||||||
|
ContinueTransmitD <= 1'b0;
|
||||||
|
end else if (NextEndDelay & ~CurrentEndDelay) begin
|
||||||
|
ContinueTransmitD <= ContinueTransmit;
|
||||||
|
end else if (EndOfSCKCS & SCLKenable) begin
|
||||||
|
ContinueTransmitD <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
always_ff @(posedge PCLK) begin
|
always_ff @(posedge PCLK) begin
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
@ -255,71 +314,68 @@ module spi_controller (
|
|||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
case (CurrState)
|
case (CurrState)
|
||||||
INACTIVE: begin // INACTIVE case --------------------------------
|
INACTIVE: if (TransmitStartD) begin
|
||||||
if (TransmitStart) begin
|
if (~HasCSSCK) NextState = TRANSMIT;
|
||||||
if (~HasCSSCK) begin
|
else NextState = CSSCK;
|
||||||
NextState = TRANSMIT;
|
|
||||||
end else begin
|
|
||||||
NextState = CSSCK;
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
NextState = INACTIVE;
|
NextState = INACTIVE;
|
||||||
end
|
end
|
||||||
end
|
CSSCK: if (EndOfCSSCK) NextState = TRANSMIT;
|
||||||
CSSCK: begin // DELAY0 case -------------------------------------
|
else NextState = CSSCK;
|
||||||
if (EndOfCSSCK) begin
|
|
||||||
NextState = TRANSMIT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
TRANSMIT: begin // TRANSMIT case --------------------------------
|
TRANSMIT: begin // TRANSMIT case --------------------------------
|
||||||
case(CSMode)
|
case(CSMode)
|
||||||
AUTOMODE: begin
|
AUTOMODE: begin
|
||||||
if (EndTransmission) begin
|
if (EndTransmission) NextState = INACTIVE;
|
||||||
NextState = INACTIVE;
|
else if (EndOfFrameDelay) NextState = SCKCS;
|
||||||
end else if (ContinueTransmit) begin
|
else NextState = TRANSMIT;
|
||||||
NextState = SCKCS;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
HOLDMODE: begin
|
HOLDMODE: begin
|
||||||
if (EndTransmission) begin
|
if (EndTransmission) NextState = HOLD;
|
||||||
NextState = HOLD;
|
else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR;
|
||||||
end else if (ContinueTransmit) begin
|
else NextState = TRANSMIT;
|
||||||
if (HasINTERXFR) NextState = INTERXFR;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
OFFMODE: begin
|
OFFMODE: begin
|
||||||
|
if (EndTransmission) NextState = INACTIVE;
|
||||||
|
else if (ContinueTransmit & HasINTERXFR) NextState = INTERXFR;
|
||||||
|
else NextState = TRANSMIT;
|
||||||
end
|
end
|
||||||
|
default: NextState = TRANSMIT;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
SCKCS: begin // SCKCS case --------------------------------------
|
SCKCS: begin // SCKCS case --------------------------------------
|
||||||
if (EndOfSCKCS) begin
|
if (EndOfSCKCS) begin
|
||||||
if (EndTransmission) begin
|
if (~ContinueTransmitD) begin
|
||||||
if (CSMode == AUTOMODE) NextState = INACTIVE;
|
// if (CSMode == AUTOMODE) NextState = INACTIVE;
|
||||||
else if (CSMode == HOLDMODE) NextState = HOLD;
|
if (CSMode == HOLDMODE) NextState = HOLD;
|
||||||
end else if (ContinueTransmit) begin
|
else NextState = INACTIVE;
|
||||||
|
end else begin
|
||||||
if (HasINTERCS) NextState = INTERCS;
|
if (HasINTERCS) NextState = INTERCS;
|
||||||
else NextState = TRANSMIT;
|
else NextState = TRANSMIT;
|
||||||
end
|
end
|
||||||
|
end else begin
|
||||||
|
NextState = SCKCS;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
HOLD: begin // HOLD mode case -----------------------------------
|
HOLD: begin // HOLD mode case -----------------------------------
|
||||||
if (CSMode == AUTOMODE) begin
|
if (CSMode == AUTOMODE) begin
|
||||||
NextState = INACTIVE;
|
NextState = INACTIVE;
|
||||||
end else if (TransmitStart) begin // If FIFO is written to, start again.
|
end else if (TransmitStartD) begin // If FIFO is written to, start again.
|
||||||
NextState = TRANSMIT;
|
NextState = TRANSMIT;
|
||||||
end
|
end else NextState = HOLD;
|
||||||
end
|
end
|
||||||
INTERCS: begin // INTERCS case ----------------------------------
|
INTERCS: begin // INTERCS case ----------------------------------
|
||||||
if (EndOfINTERCS) begin
|
if (EndOfINTERCS) begin
|
||||||
if (HasCSSCK) NextState = CSSCK;
|
if (HasCSSCK) NextState = CSSCK;
|
||||||
else NextState = TRANSMIT;
|
else NextState = TRANSMIT;
|
||||||
|
end else begin
|
||||||
|
NextState = INTERCS;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
INTERXFR: begin // INTERXFR case --------------------------------
|
INTERXFR: begin // INTERXFR case --------------------------------
|
||||||
if (EndOfINTERXFR) begin
|
if (EndOfINTERXFR) begin
|
||||||
NextState = TRANSMIT;
|
NextState = TRANSMIT;
|
||||||
|
end else begin
|
||||||
|
NextState = INTERXFR;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
default: begin
|
default: begin
|
||||||
@ -330,19 +386,6 @@ module spi_controller (
|
|||||||
|
|
||||||
assign Transmitting = CurrState == TRANSMIT;
|
assign Transmitting = CurrState == TRANSMIT;
|
||||||
assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR);
|
assign DelayIsNext = (NextState == CSSCK | NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR);
|
||||||
|
assign InactiveState = CurrState == INACTIVE | CurrState == INTERCS;
|
||||||
//
|
|
||||||
always_ff @(posedge PCLK) begin
|
|
||||||
if (~PRESETn) begin
|
|
||||||
TransmitReg <= 8'b0;
|
|
||||||
end else if (TransmitLoad) begin
|
|
||||||
TransmitReg <= txFIFORead;
|
|
||||||
end else if (ShiftEdge) begin
|
|
||||||
TransmitReg <= {TransmitReg[6:0], TransmitReg[0]};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign SPIOUT = TransmitReg[7];
|
|
||||||
assign CS = CurrState == INACTIVE | CurrState == INTERCS;
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@ -72,7 +72,8 @@ string coverage64gc[] = '{
|
|||||||
"pmpcfg2",
|
"pmpcfg2",
|
||||||
"pmppriority",
|
"pmppriority",
|
||||||
"pmpcbo",
|
"pmpcbo",
|
||||||
"pmpadrdecs"
|
"pmpadrdecs",
|
||||||
|
"btbthrash"
|
||||||
};
|
};
|
||||||
|
|
||||||
string buildroot[] = '{
|
string buildroot[] = '{
|
||||||
|
|||||||
145
tests/coverage/btbthrash.S
Normal file
145
tests/coverage/btbthrash.S
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// btbtrash.S
|
||||||
|
//
|
||||||
|
// Written: Rose Thompson rose@rosethompson.net 23 October 2024
|
||||||
|
//
|
||||||
|
// Purpose: Test the branch target buffer alias with divide and cache pipeline stalls
|
||||||
|
//
|
||||||
|
// A component of the CORE-V-WALLY configurable RISC-V project.
|
||||||
|
// https://github.com/openhwgroup/cvw
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// load code to initalize stack, handle interrupts, terminate
|
||||||
|
#include "WALLY-init-lib.h"
|
||||||
|
|
||||||
|
main:
|
||||||
|
|
||||||
|
# Division test (having trouble with buildroot)
|
||||||
|
li x1, 1938759018
|
||||||
|
li x2, 3745029
|
||||||
|
li x3, 458
|
||||||
|
li x4, 29587209347
|
||||||
|
li x5, 28957
|
||||||
|
li x6, 298
|
||||||
|
li x7, 238562
|
||||||
|
li x8, 198674
|
||||||
|
li x9, 134
|
||||||
|
li x10, 906732
|
||||||
|
li x11, 29
|
||||||
|
li x12, 50912
|
||||||
|
li x13, 59
|
||||||
|
li x14, 6902385
|
||||||
|
li x15, 1923857
|
||||||
|
li x16, 3985
|
||||||
|
li x17, 3947
|
||||||
|
li x18, 15984
|
||||||
|
li x19, 5
|
||||||
|
li x20, 9684658489
|
||||||
|
li x21, 6548
|
||||||
|
li x22, 3564
|
||||||
|
li x23, 94
|
||||||
|
li x24, 689464
|
||||||
|
li x25, 42567
|
||||||
|
li x26, 98453
|
||||||
|
li x27, 648
|
||||||
|
li x28, 984
|
||||||
|
li x29, 6984
|
||||||
|
li x30, 864
|
||||||
|
|
||||||
|
# x31 will be our loop counter
|
||||||
|
li x31, 4
|
||||||
|
|
||||||
|
.align 12
|
||||||
|
jump1:
|
||||||
|
divuw x0, x1, x2
|
||||||
|
j jump3
|
||||||
|
jump4:
|
||||||
|
divuw x0, x5, x6
|
||||||
|
j jump5
|
||||||
|
jump6:
|
||||||
|
divuw x0, x10, x9
|
||||||
|
j jump7
|
||||||
|
jump8:
|
||||||
|
divuw x0, x14, x3
|
||||||
|
j jump9
|
||||||
|
jump10:
|
||||||
|
divuw x0, x18, x17
|
||||||
|
j jump11
|
||||||
|
jump12:
|
||||||
|
divuw x0, x21, x22
|
||||||
|
j jump13
|
||||||
|
jump14:
|
||||||
|
divuw x0, x24, x25
|
||||||
|
j jump15
|
||||||
|
jump16:
|
||||||
|
divuw x0, x29, x28
|
||||||
|
j jump17
|
||||||
|
jump18:
|
||||||
|
divuw x0, x1, x30
|
||||||
|
j jump19
|
||||||
|
jump20:
|
||||||
|
divuw x0, x3, x19
|
||||||
|
j jump21
|
||||||
|
jump22:
|
||||||
|
divuw x0, x12, x13
|
||||||
|
j jump23
|
||||||
|
|
||||||
|
.align 12 # size of the 1024 btb apart
|
||||||
|
jump2:
|
||||||
|
j jump1
|
||||||
|
jump3:
|
||||||
|
divuw x0, x4, x3
|
||||||
|
j jump4
|
||||||
|
jump5:
|
||||||
|
divuw x0, x7, x8
|
||||||
|
j jump6
|
||||||
|
jump7:
|
||||||
|
divuw x0, x12, x11
|
||||||
|
j jump8
|
||||||
|
jump9:
|
||||||
|
divuw x0, x15, x16
|
||||||
|
j jump10
|
||||||
|
jump11:
|
||||||
|
divuw x0, x20, x19
|
||||||
|
j jump12
|
||||||
|
jump13:
|
||||||
|
divuw x0, x24, x23
|
||||||
|
j jump14
|
||||||
|
jump15:
|
||||||
|
divuw x0, x26, x27
|
||||||
|
j jump16
|
||||||
|
jump17:
|
||||||
|
divuw x0, x29, x30
|
||||||
|
j jump18
|
||||||
|
jump19:
|
||||||
|
divuw x0, x2, x3
|
||||||
|
j jump20
|
||||||
|
jump21:
|
||||||
|
divuw x0, x4, x5
|
||||||
|
j jump22
|
||||||
|
jump23:
|
||||||
|
divuw x0, x20, x21
|
||||||
|
#j jump22
|
||||||
|
|
||||||
|
fence.i
|
||||||
|
|
||||||
|
addi x31, x31, -1
|
||||||
|
bne x31, x0, jump1
|
||||||
|
finsihed:
|
||||||
|
j done
|
||||||
|
|
||||||
@ -238,46 +238,6 @@
|
|||||||
|
|
||||||
0000001F
|
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
|
00000001 #watermark interrupts
|
||||||
|
|
||||||
00000000 #read mip
|
00000000 #read mip
|
||||||
|
|||||||
@ -547,108 +547,13 @@ test_cases:
|
|||||||
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
#.4byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||||
#.4byte rx_data, 0x000000F0, read32_test # read rx_data
|
#.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 watermark interrupts ===========
|
||||||
|
|
||||||
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||||
|
|
||||||
SETUP_PLIC
|
SETUP_PLIC
|
||||||
|
.4byte fmt, 0x00080000, write32_test # reset format register
|
||||||
.4byte delay1, 0x0000001, write32_test # reset delay1 register
|
.4byte delay1, 0x0000001, write32_test # reset delay1 register
|
||||||
.4byte cs_mode, 0x00000000, write32_test # reset cs_mode
|
.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 tx_mark, 0x00000001, write32_test # set transmit watermark to 1 (any entry turns mark off)
|
||||||
|
|||||||
@ -238,46 +238,6 @@
|
|||||||
00000000
|
00000000
|
||||||
0000001F
|
0000001F
|
||||||
00000000
|
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
|
00000001 #watermark interrupts
|
||||||
00000000
|
00000000
|
||||||
00000000 #read mip
|
00000000 #read mip
|
||||||
|
|||||||
@ -551,94 +551,6 @@ test_cases:
|
|||||||
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
#.8byte 0x0, 0x00000000, spi_data_wait # wait for transmission to end
|
||||||
#.8byte rx_data, 0x000000F0, read32_test # read rx_data
|
#.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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -652,7 +564,7 @@ test_cases:
|
|||||||
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
# Test transmit watermark interrupt (triggers when entries in tx FIFO < tx watermark) without external enables
|
||||||
|
|
||||||
SETUP_PLIC
|
SETUP_PLIC
|
||||||
|
.8byte fmt, 0x00080000, write32_test # reset format register
|
||||||
.8byte delay1, 0x0000001, write32_test # reset delay1 register
|
.8byte delay1, 0x0000001, write32_test # reset delay1 register
|
||||||
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode
|
.8byte cs_mode, 0x00000000, write32_test # reset cs_mode
|
||||||
.8byte sck_div, 0x00000100, write32_test # lower SPI clock rate so reads are done at correct time when ICACHE not supported
|
.8byte sck_div, 0x00000100, write32_test # lower SPI clock rate so reads are done at correct time when ICACHE not supported
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user