Initial version of FSI master and associated testbench

This core implements the (relatively poorly documented) OpenFSI 1.0.0
specification available from the OpenPOWER Foundation.

Considerable uncertainty exists surrounding error recovery and whether
any extant FSI slaves honor error recovery actions undertaken during
I_POLL command processing, thus error recovery is controlled by two
independent enable bits in case incomaptible slaves are enountered
in the wild.
parent 22688f67
......@@ -19,13 +19,13 @@ lpc_spi_bridge_%.int: lpc_spi_bridge.json timing_constraints.py main.pcf
lpc_spi_bridge.int: lpc_spi_bridge_1.int
cp lpc_spi_bridge_1.int lpc_spi_bridge.int
lpc_spi_bridge.json: main.v lpc_interface.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES)
lpc_spi_bridge.json: main.v lpc_interface.v fsi_master.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES)
yosys -l yosys.log -q -p "synth_ice40 -top lpc_bridge_top -json lpc_spi_bridge.json" main.v
lpc_spi_bridge.ex: lpc_spi_bridge.int
icebox_explain lpc_spi_bridge.int > lpc_spi_bridge.ex
lpc_spi_bridge_postsynth_sim.blif: main.v lpc_interface.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES) timing_constraints.py main.pcf
lpc_spi_bridge_postsynth_sim.blif: main.v lpc_interface.v fsi_master.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES) timing_constraints.py main.pcf
yosys -l yosys_postsynth.log -q -f "verilog -DSIMULATION -DPOST_SYNTHESIS" -p "synth_ice40 -top lpc_bridge_top -blif lpc_spi_bridge_postsynth_sim.blif" main.v
lpc_spi_bridge_postsynth_sim.v: lpc_spi_bridge_postsynth_sim.blif
......@@ -61,7 +61,7 @@ dump_toolchain_info:
-@arachne-pnr -v 2>/dev/null
-@echo "================================================================================"
lpc_interface_test.vcd: main.v lpc_interface.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES) testbench_lpc.v
lpc_interface_test.vcd: main.v lpc_interface.v fsi_master.v spi_master.v ipmi_bt_slave.v flash_block_cache.v simple_rtc.v clock_generator.v $(UART_CORE_FILES) testbench_lpc.v
rm -f lpc_interface_sim
rm -f lpc_interface_test.vcd
/usr/bin/iverilog -DSIMULATION -o lpc_interface_sim main.v spi_master.v simple_rtc.v clock_generator.v $(UART_CORE_FILES) testbench_lpc.v
......@@ -72,6 +72,17 @@ simulate_lpc: lpc_interface_test.vcd
simulate_lpc_view: lpc_interface_test.vcd
gtkwave lpc_interface_test.vcd
fsi_interface_test.vcd: fsi_master.v testbench_fsi.v
rm -f fsi_interface_sim
rm -f fsi_interface_test.vcd
/usr/bin/iverilog -DSIMULATION -o fsi_interface_sim fsi_master.v testbench_fsi.v
./fsi_interface_sim
simulate_fsi: fsi_interface_test.vcd
simulate_fsi_view: fsi_interface_test.vcd
gtkwave fsi_interface_test.vcd
test: lpc_spi_bridge.bin
iceprog -S lpc_spi_bridge.bin
......@@ -79,4 +90,4 @@ flash: lpc_spi_bridge.bin
iceprog lpc_spi_bridge.bin
clean:
rm -f lpc_spi_bridge.json lpc_spi_bridge_postsynth_sim.blif lpc_spi_bridge_postsynth_sim.v lpc_spi_bridge.ex lpc_spi_bridge.int lpc_spi_bridge.tmg lpc_spi_bridge_*.int lpc_spi_bridge_*.tmg blank.rom lpc_spi_bridge.rom lpc_interface_sim lpc_interface_test.vcd yosys.log
rm -f lpc_spi_bridge.json lpc_spi_bridge_postsynth_sim.blif lpc_spi_bridge_postsynth_sim.v lpc_spi_bridge.ex lpc_spi_bridge.int lpc_spi_bridge.tmg lpc_spi_bridge_*.int lpc_spi_bridge_*.tmg blank.rom lpc_spi_bridge.rom lpc_interface_sim lpc_interface_test.vcd fsi_interface_sim fsi_interface_test.vcd yosys.log
This diff is collapsed.
// © 2020 Raptor Engineering, LLC
//
// Released under the terms of the AGPL v3
// See the LICENSE file for full details
`timescale 1ns / 100ps
// Main testbench
module fsi_test();
reg peripheral_reset = 1;
reg peripheral_clock = 0;
reg [1:0] slave_id = 0;
reg [20:0] address = 0;
reg [31:0] tx_data = 0;
wire [31:0] rx_data;
reg [1:0] data_length = 0;
reg data_direction = 0;
reg start_cycle = 0;
wire cycle_complete;
wire [2:0] cycle_error;
reg [1:0] enhanced_error_recovery = 2'b11;
reg enable_ipoll = 1;
wire fsi_data_out;
reg fsi_data_in = 0;
wire fsi_data_direction;
wire fsi_clock_out;
wire ipoll_error;
fsi_master_interface U1(
.slave_id(slave_id),
.address(address),
.tx_data(tx_data),
.rx_data(rx_data),
.data_length(data_length),
.data_direction(data_direction),
.start_cycle(start_cycle),
.cycle_complete(cycle_complete),
.cycle_error(cycle_error),
.enhanced_error_recovery(enhanced_error_recovery),
.enable_ipoll(enable_ipoll),
.ipoll_error(ipoll_error),
.fsi_data_out(fsi_data_out),
.fsi_data_in(fsi_data_in),
.fsi_data_direction(fsi_data_direction),
.fsi_clock_out(fsi_clock_out),
.peripheral_reset(peripheral_reset),
.peripheral_clock(peripheral_clock)
);
initial begin
$dumpfile("fsi_interface_test.vcd"); // Dumpfile
$dumpvars; // Dump all signals
end
always
#3 peripheral_clock = ~peripheral_clock; // Main 166.7MHz clock
initial begin
#15 // Wait for clock to stabilize
peripheral_reset = 0; // Bring core out of reset
#1554 // Wait for post-reset BREAK command to finish
data_direction = 0; // Drive read request
slave_id = 0; // Absolute addressing since it is the first transfer after reset
address = 21'h012345; // 33'b100100100001001000110100010111000, CRC protected portion: 29'h1242468B, CRC: 4'h8
//address = 21'h154321; // 33'b100100110101010000110010000111100, CRC protected portion: 29'h126A8643, CRC: 4'hc
//address = 21'h054321; // 33'b100100100101010000110010000111011, CRC protected portion: 29'h124A8643, CRC: 4'hb
//address = 21'h050321; // 33'b100100100101000000110010000110101, CRC protected portion: 29'h124A0643, CRC: 4'h5
data_length = 2; // 32 bit transfer
start_cycle = 1; // Start cycle
#222
fsi_data_in = 1'b1; // Transmit ACK_D response, 37'b10000011101100101010000110010000100001011
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#24
start_cycle = 0; // End cycle
#48
data_direction = 0; // Drive read request
slave_id = 0; // Relative addressing since it is within 256 bytes of the previous transfer address
address = 21'h012344;
data_length = 2; // 32 bit transfer
start_cycle = 1; // Start cycle
#1200
fsi_data_in = 1'b1; // Transmit BUSY response, 9'b100010101
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit BUSY response, 9'b100010101
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit ERR_C response, 9'b100111011
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit BUSY response, 9'b100010101
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit ***corrupted*** BUSY response, 9'b100010100
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit BUSY response, 9'b100010101
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit ACK_D response, 37'b10000011101100101010000110010000100001011
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#24
start_cycle = 0; // End cycle
#1200 // System will run an IPOLL if left idle for this length of time
fsi_data_in = 1'b1; // Transmit ***corrupt*** I_POLL_RSP response, 13'b1000010100001
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
#1200
fsi_data_in = 1'b1; // Transmit I_POLL_RSP response, 13'b1000010100001
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b0;
#6
fsi_data_in = 1'b1;
#6
fsi_data_in = 1'b0; // Return to idle
end
initial
#30000 $finish; // Terminate after 30µs
endmodule
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment