mirror of https://github.com/efabless/caravel.git
add new test spi_master_rd
This commit is contained in:
parent
a00d62ebcf
commit
79f26f6b38
|
@ -36,6 +36,7 @@ from tests.gpio.gpio import *
|
|||
from tests.mgmt_gpio.mgmt_gpio import *
|
||||
from tests.timer.timer import *
|
||||
from tests.uart.uart import *
|
||||
from tests.spi_master.spi_master import *
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ caravel uut (
|
|||
|
||||
|
||||
// make speical variables for the mprj input to assign the input without writing to the output gpios
|
||||
// cocotb limitation #2587
|
||||
// cocotb limitation #2587: iverilog deal with array as 1 object not multiple of objects so can't write to only 1 element
|
||||
wire bin0;
|
||||
wire bin0_en;
|
||||
wire bin1;
|
||||
|
@ -229,6 +229,87 @@ caravel uut (
|
|||
assign mprj_io_tb[36] = (bin36_en) ? bin36 : 1'bz;
|
||||
assign mprj_io_tb[37] = (bin37_en) ? bin37 : 1'bz;
|
||||
|
||||
|
||||
|
||||
// to read from mprj array with iverilog
|
||||
wire bin0_monitor;
|
||||
wire bin1_monitor;
|
||||
wire bin2_monitor;
|
||||
wire bin3_monitor;
|
||||
wire bin4_monitor;
|
||||
wire bin5_monitor;
|
||||
wire bin6_monitor;
|
||||
wire bin7_monitor;
|
||||
wire bin8_monitor;
|
||||
wire bin9_monitor;
|
||||
wire bin10_monitor;
|
||||
wire bin11_monitor;
|
||||
wire bin12_monitor;
|
||||
wire bin13_monitor;
|
||||
wire bin14_monitor;
|
||||
wire bin15_monitor;
|
||||
wire bin16_monitor;
|
||||
wire bin17_monitor;
|
||||
wire bin18_monitor;
|
||||
wire bin19_monitor;
|
||||
wire bin20_monitor;
|
||||
wire bin21_monitor;
|
||||
wire bin22_monitor;
|
||||
wire bin23_monitor;
|
||||
wire bin24_monitor;
|
||||
wire bin25_monitor;
|
||||
wire bin26_monitor;
|
||||
wire bin27_monitor;
|
||||
wire bin28_monitor;
|
||||
wire bin29_monitor;
|
||||
wire bin30_monitor;
|
||||
wire bin31_monitor;
|
||||
wire bin32_monitor;
|
||||
wire bin33_monitor;
|
||||
wire bin34_monitor;
|
||||
wire bin35_monitor;
|
||||
wire bin36_monitor;
|
||||
wire bin37_monitor;
|
||||
|
||||
assign bin0_monitor = mprj_io_tb[0];
|
||||
assign bin1_monitor = mprj_io_tb[1];
|
||||
assign bin2_monitor = mprj_io_tb[2];
|
||||
assign bin3_monitor = mprj_io_tb[3];
|
||||
assign bin4_monitor = mprj_io_tb[4];
|
||||
assign bin5_monitor = mprj_io_tb[5];
|
||||
assign bin6_monitor = mprj_io_tb[6];
|
||||
assign bin7_monitor = mprj_io_tb[7];
|
||||
assign bin8_monitor = mprj_io_tb[8];
|
||||
assign bin9_monitor = mprj_io_tb[9];
|
||||
assign bin10_monitor = mprj_io_tb[10];
|
||||
assign bin11_monitor = mprj_io_tb[11];
|
||||
assign bin12_monitor = mprj_io_tb[12];
|
||||
assign bin13_monitor = mprj_io_tb[13];
|
||||
assign bin14_monitor = mprj_io_tb[14];
|
||||
assign bin15_monitor = mprj_io_tb[15];
|
||||
assign bin16_monitor = mprj_io_tb[16];
|
||||
assign bin17_monitor = mprj_io_tb[17];
|
||||
assign bin18_monitor = mprj_io_tb[18];
|
||||
assign bin19_monitor = mprj_io_tb[19];
|
||||
assign bin20_monitor = mprj_io_tb[20];
|
||||
assign bin21_monitor = mprj_io_tb[21];
|
||||
assign bin22_monitor = mprj_io_tb[22];
|
||||
assign bin23_monitor = mprj_io_tb[23];
|
||||
assign bin24_monitor = mprj_io_tb[24];
|
||||
assign bin25_monitor = mprj_io_tb[25];
|
||||
assign bin26_monitor = mprj_io_tb[26];
|
||||
assign bin27_monitor = mprj_io_tb[27];
|
||||
assign bin28_monitor = mprj_io_tb[28];
|
||||
assign bin29_monitor = mprj_io_tb[29];
|
||||
assign bin30_monitor = mprj_io_tb[30];
|
||||
assign bin31_monitor = mprj_io_tb[31];
|
||||
assign bin32_monitor = mprj_io_tb[32];
|
||||
assign bin33_monitor = mprj_io_tb[33];
|
||||
assign bin34_monitor = mprj_io_tb[34];
|
||||
assign bin35_monitor = mprj_io_tb[35];
|
||||
assign bin36_monitor = mprj_io_tb[36];
|
||||
assign bin37_monitor = mprj_io_tb[37];
|
||||
|
||||
endmodule
|
||||
|
||||
// module that has all needed macros by cocotb
|
||||
|
|
|
@ -169,5 +169,12 @@
|
|||
"GL":["nightly","weekly","tape_out"],
|
||||
"GL_SDF":["weekly","tape_out"],
|
||||
"description":"test uart reception"}
|
||||
|
||||
,"spi_master_rd" :{"level":0,
|
||||
"SW":true,
|
||||
"RTL":["setup","nightly","weekly","tape_out"],
|
||||
"GL":["nightly","weekly","tape_out"],
|
||||
"GL_SDF":["weekly","tape_out"],
|
||||
"description":"using SPI master for reading from external memory"}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
|
||||
import random
|
||||
import cocotb
|
||||
from cocotb.triggers import FallingEdge,RisingEdge,ClockCycles,Timer
|
||||
import cocotb.log
|
||||
from tests.common_functions.test_functions import *
|
||||
from tests.bitbang.bitbang_functions import *
|
||||
|
||||
|
||||
#VIP for SPI
|
||||
"""
|
||||
support commands
|
||||
00000000 -> No operation
|
||||
00000011 -> Read in streaming mode
|
||||
"""
|
||||
async def SPI_VIP(csb,clk,SDI,SDO,mem):
|
||||
while True:
|
||||
await FallingEdge(csb)
|
||||
cocotb.log.info (f"[SPI_VIP] CSB is asserted operation has begin ")
|
||||
op = await cocotb.start(SPI_op(clk,SDI,SDO,mem))
|
||||
await csb_watcher(csb,op)
|
||||
cocotb.log.info (f"[SPI_VIP] CSB is deasserted operation has been killed")
|
||||
|
||||
# cocotb.scheduler.add
|
||||
# watch the csb and when it's diable kill the SPI_op thread
|
||||
async def csb_watcher(csb,thread):
|
||||
cocotb.log.info (f"[csb_watcher] start CSB watching")
|
||||
await RisingEdge(csb)
|
||||
thread.kill()
|
||||
|
||||
# detect command and address and apply the command
|
||||
async def SPI_op(clk,SDI,SDO,mem):
|
||||
address =''
|
||||
command =''
|
||||
await RisingEdge(clk)
|
||||
# command
|
||||
for i in range(8):
|
||||
command = command + SDI.value.binstr
|
||||
await RisingEdge(clk)
|
||||
cocotb.log.info (f"[SPI_VIP] [SPI_op] command = {command}")
|
||||
# address
|
||||
address =''
|
||||
for i in range(8*3): # address is 3 parts each part are 8 bits
|
||||
address = address + SDI.value.binstr
|
||||
if i != 23: # skip last cycle wait
|
||||
await RisingEdge(clk)
|
||||
cocotb.log.info (f"[SPI_VIP] [SPI_op] address = {address}")
|
||||
address = int(address,2)
|
||||
#data
|
||||
if command == "10000000" and False: # not sure about the read command
|
||||
for i in range(8):
|
||||
data_in += SDI
|
||||
await RisingEdge(clk)
|
||||
elif command == "00000011":
|
||||
await FallingEdge(clk)
|
||||
while True:
|
||||
data = bin(mem[address])[2:].zfill(8)
|
||||
for i in range(8):
|
||||
SDO[0].value = 1 # enable
|
||||
SDO[1].value = int(data[i],2) # bin
|
||||
cocotb.log.debug (f"[SPI_VIP] [SPI_op] SDO = {data[i]} ")
|
||||
await FallingEdge(clk)
|
||||
SDO[0].value = 0 # enable
|
||||
|
||||
cocotb.log.info (f"[SPI_VIP] [SPI_op] finish reading address {hex(address) } data = {hex(int(data,2))} ")
|
||||
address +=1
|
||||
|
||||
|
||||
def read_mem (file_name):
|
||||
with open(file_name, 'r') as file:
|
||||
lines = file.readlines()
|
||||
mem = dict()
|
||||
for line in lines:
|
||||
if line[0] == "@":
|
||||
address = int(line[1:],16)
|
||||
cocotb.log.debug (f" found line = {line} address = {hex(address)} ")
|
||||
else:
|
||||
line_no_space = line.strip().replace(' ','')
|
||||
for i in range (0,len(line_no_space),2):
|
||||
cocotb.log.debug (f" i = {i} ine_no_space[{i}:{i+2}] = {line_no_space[i:i+2]} address = {hex(address)}")
|
||||
mem[address] = int(line_no_space[i:i+2],16)
|
||||
address +=1
|
||||
cocotb.log.debug (f" found line = {line} line_no_space = {line_no_space} size = {len(line_no_space)}")
|
||||
cocotb.log.info (f"[read_mem] SPI mem = {mem}")
|
||||
return mem
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import random
|
||||
import cocotb
|
||||
from cocotb.triggers import FallingEdge,RisingEdge,ClockCycles,Timer
|
||||
import cocotb.log
|
||||
from cpu import RiskV
|
||||
from defsParser import Regs
|
||||
from cocotb.result import TestSuccess
|
||||
from tests.common_functions.test_functions import *
|
||||
from tests.spi_master.SPI_VIP import read_mem ,SPI_VIP
|
||||
from caravel import GPIO_MODE
|
||||
|
||||
|
||||
bit_time_ns = 0
|
||||
reg = Regs()
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
@repot_test
|
||||
async def spi_master_rd(dut):
|
||||
""" the firmware is configured to always send clk to spi so I can't insert alot of logics reading values
|
||||
|
||||
the method of testing used can't work if 2 addresses Consecutive have the same address
|
||||
"""
|
||||
|
||||
caravelEnv,clock = await test_configure(dut,timeout_cycles=214842)
|
||||
cpu = RiskV(dut)
|
||||
cpu.cpu_force_reset()
|
||||
cpu.cpu_release_reset()
|
||||
cocotb.log.info (f"[TEST] start spi_master_rd test")
|
||||
file_name = f"{os.getenv('CARAVEL_VERILOG_PATH')}/dv/cocotb/tests/spi_master/test_data"
|
||||
mem = read_mem(file_name)
|
||||
await cocotb.start(SPI_VIP(dut.bin33_monitor,dut.bin32_monitor,dut.bin35_monitor,(dut.bin34_en,dut.bin34),mem)) # fork for SPI
|
||||
|
||||
addresses_to_read = (0x04,0x05,0x06,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf) # the addresses that the firmware read from mem file
|
||||
await wait_reg2(cpu,caravelEnv,0XAA)
|
||||
cocotb.log.info (f"[TEST] GPIO configuration finished ans start reading from mememory")
|
||||
val =0
|
||||
for address in addresses_to_read:
|
||||
# await wait_reg2(cpu,caravelEnv,0x55) # value is ready to be read
|
||||
#wait until value change
|
||||
while True:
|
||||
if val != cpu.read_debug_reg1():
|
||||
break
|
||||
await ClockCycles(caravelEnv.clk,100)
|
||||
|
||||
expected_val = mem[address]
|
||||
val = cpu.read_debug_reg1()
|
||||
if val == expected_val:
|
||||
cocotb.log.info(f"[TEST] correct read of value {hex(val)} from address {hex(address)} ")
|
||||
else:
|
||||
cocotb.log.error(f"[TEST] wrong read from address {hex(address)} expected value = {hex(expected_val)} value {hex(val)} ")
|
||||
# cpu.write_debug_reg2_backdoor(0xCC)
|
||||
|
||||
await ClockCycles(caravelEnv.clk,1000)
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* 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.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <defs.h>
|
||||
#include <csr.h>
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
/*
|
||||
* SPI master Test
|
||||
* - Enables SPI master
|
||||
* - Uses SPI master to talk to external SPI module
|
||||
*/
|
||||
|
||||
void spi_write(char c)
|
||||
{
|
||||
reg_spimaster_wdata = (unsigned long) c;
|
||||
// reg_spimaster_wdata = c;
|
||||
// spi_master_control_length_write(8);
|
||||
// spi_master_control_start_write(1);
|
||||
// reg_spimaster_control = 0x0800;
|
||||
reg_spimaster_control = 0x0801;
|
||||
}
|
||||
char spi_read()
|
||||
{
|
||||
// reg_spimaster_wdata = c;
|
||||
// spi_master_control_length_write(8);
|
||||
// spi_master_control_start_write(1);
|
||||
// reg_spimaster_control = 0x0800;
|
||||
// spi_write(0x00);
|
||||
// reg_spimaster_rdata = 0x00;
|
||||
// reg_spimaster_control = 0x0801;
|
||||
spi_write(0x00);
|
||||
while (reg_spimaster_status != 1);
|
||||
return reg_spimaster_rdata;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int i;
|
||||
uint32_t value;
|
||||
reg_wb_enable =1; // for enable writing to reg_debug_1 and reg_debug_2
|
||||
reg_debug_1 = 0x0;
|
||||
reg_debug_2 = 0x0;
|
||||
|
||||
// For SPI operation, GPIO 1 should be an input, and GPIOs 2 to 4
|
||||
// should be outputs.
|
||||
|
||||
reg_mprj_io_34 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; // SDI
|
||||
reg_mprj_io_35 = GPIO_MODE_MGMT_STD_BIDIRECTIONAL; // SDO
|
||||
reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; // CSB
|
||||
reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; // SCK
|
||||
|
||||
/* Apply configuration */
|
||||
reg_mprj_xfer = 1;
|
||||
while (reg_mprj_xfer == 1);
|
||||
|
||||
reg_debug_2 =0xAA;
|
||||
|
||||
reg_spi_enable = 1;
|
||||
|
||||
|
||||
// For SPI operation, GPIO 1 should be an input, and GPIOs 2 to 4
|
||||
// should be outputs.
|
||||
|
||||
// Start test
|
||||
|
||||
// Enable SPI master
|
||||
// SPI master configuration bits:
|
||||
// bits 7-0: Clock prescaler value (default 2)
|
||||
// bit 8: MSB/LSB first (0 = MSB first, 1 = LSB first)
|
||||
// bit 9: CSB sense (0 = inverted, 1 = noninverted)
|
||||
// bit 10: SCK sense (0 = noninverted, 1 = inverted)
|
||||
// bit 11: mode (0 = read/write opposite edges, 1 = same edges)
|
||||
// bit 12: stream (1 = CSB ends transmission)
|
||||
// bit 13: enable (1 = enabled)
|
||||
// bit 14: IRQ enable (1 = enabled)
|
||||
// bit 15: (unused)
|
||||
|
||||
|
||||
reg_spimaster_cs = 0x10001; // sel=0, manual CS
|
||||
|
||||
spi_write(0x03); // Write 0x03 (read mode)
|
||||
spi_write(0x00); // Write 0x00 (start address high byte)
|
||||
spi_write(0x00); // Write 0x00 (start address middle byte)
|
||||
spi_write(0x04); // Write 0x04 (start address low byte)
|
||||
|
||||
value = spi_read(); // 0x93
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
|
||||
value = spi_read(); // 0x01
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read(); // 0x00
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
reg_spimaster_cs = 0x0000; // release CS
|
||||
reg_spimaster_cs = 0x10001; // sel=0, manual CS
|
||||
|
||||
spi_write(0x03); // Write 0x03 (read mode)
|
||||
spi_write(0x00); // Write 0x00 (start address high byte)
|
||||
spi_write(0x00); // Write 0x00 (start address middle byte)
|
||||
spi_write(0x08); // Write 0x08 (start address low byte)
|
||||
|
||||
value = spi_read(); // 0x13
|
||||
if (value == 0x13)
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read(); // 0x02
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
reg_spimaster_cs = 0x0000; // release CS
|
||||
reg_spimaster_cs = 0x10001; // sel=0, manual CS
|
||||
|
||||
spi_write(0x03); // Write 0x03 (read mode)
|
||||
spi_write(0x00); // Write 0x00 (start address high byte)
|
||||
spi_write(0x00); // Write 0x00 (start address middle byte)
|
||||
spi_write(0x0a); // Write 0x0a (start address low byte)
|
||||
|
||||
value = spi_read(); // 0x63
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read(); // 0x57
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read(); // 0xb5
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read(); // 0x00
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
value = spi_read();// 0x23
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
|
||||
value = spi_read(); // 0x20
|
||||
reg_debug_1 = value;
|
||||
// reg_debug_2 =0x55; // value is ready to be read
|
||||
// while (reg_debug_2 != 0xCC) // testbench has read the value
|
||||
|
||||
reg_spimaster_cs = 0x0000; // release CS
|
||||
reg_spimaster_cs = 0x10001; // sel=0, manual CS
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@00000000
|
||||
6F 00 00 0B 93 01 00 00 13 02 63 57 b5 00 23 20
|
||||
13 00 00 00 13 00 00 00 13 00 00 00 13 00 00 00
|
Loading…
Reference in New Issue