Branch: master

cd7e1ea3 2019-04-29 00:33:00 Timothy Pearson
Add user logic reset support to serial version of FPGA control interface
M fpga/serial/common/remote_access.v
M fpga/serial/lattice/eb85/control_fpga.pcf
M fpga/serial/lattice/eb85/main.v

fpga/serial/common/remote_access.v

diff --git a/fpga/serial/common/remote_access.v b/fpga/serial/common/remote_access.v
index e30006f..9afdbf2 100644
--- a/fpga/serial/common/remote_access.v
+++ b/fpga/serial/common/remote_access.v
@@ -23,6 +23,7 @@
 
 module remote_access(
 	input main_fifty_clock,				// 50MHz clock in
+	output user_logic_reset,			// Active high user logic reset out
 	input [3:0] remote_access_4_bit_output,		// 4 bit output from the user program to remote access client
 	output [3:0] remote_access_4_bit_input,		// 4 bit input from the remote access client to user program
 	input [7:0] remote_access_8_bit_output,		// 8 bit output from the user program to remote access client
@@ -66,6 +67,8 @@
 `ifndef SYSTEM_HAS_SRAM
 	reg sram_processing_done = 1'b1;
 `endif
+
+	reg user_logic_reset_reg = 1'b0;
 	
 	reg [7:0] remote_access_4_bit_input_reg;
 	reg [7:0] remote_access_8_bit_input_reg;
@@ -79,6 +82,7 @@
 	reg sram_available_reg;
 	reg startup_needed = 1;
 	
+	assign user_logic_reset = user_logic_reset_reg;
 	assign remote_access_4_bit_input = remote_access_4_bit_input_reg[3:0];
 	assign remote_access_8_bit_input = remote_access_8_bit_input_reg;
 	assign remote_access_16_bit_input = remote_access_16_bit_input_reg;
@@ -622,6 +626,9 @@
 		end
 	
 		if (RxD_data_ready == 1) begin
+			// Release user logic reset if set on previous serial receive cycle
+			user_logic_reset_reg = 1'b0;
+
 			if (serial_character_received == 0) begin
 				serial_rx_data_reg = RxD_data;
 				serial_rx_strobe_reg = 1;		// Signal new data...
@@ -757,6 +764,11 @@
 									// Transmit the DSP RAM size
 									transmit_dsp_ram_size = 1;
 								end
+
+								if (serial_command_buffer == 82) begin
+									// Strobe user logic reset
+									user_logic_reset_reg = 1'b1;
+								end
 							end else begin
 								if (next_byte_is_command == 1) begin
 									// The previous byte was the command--now load in the data!

fpga/serial/lattice/eb85/control_fpga.pcf

diff --git a/fpga/serial/lattice/eb85/control_fpga.pcf b/fpga/serial/lattice/eb85/control_fpga.pcf
index ddcaaa2..d2c37a2 100644
--- a/fpga/serial/lattice/eb85/control_fpga.pcf
+++ b/fpga/serial/lattice/eb85/control_fpga.pcf
@@ -19,6 +19,8 @@
 set_io led_bank[0] B5
 
 # Guest FPGA interface
+set_io guest_logic_reset A16
+
 set_io four_bit_output[3] C16
 set_io four_bit_output[2] D16
 set_io four_bit_output[1] E16

fpga/serial/lattice/eb85/main.v

diff --git a/fpga/serial/lattice/eb85/main.v b/fpga/serial/lattice/eb85/main.v
index e736781..58c2a1e 100644
--- a/fpga/serial/lattice/eb85/main.v
+++ b/fpga/serial/lattice/eb85/main.v
@@ -11,6 +11,8 @@
 		input wire main_12_mhz_clock,
 
 		// Guest FPGA interface
+		output wire guest_logic_reset,		// Active high guest logic reset signal
+
 		input wire [3:0] four_bit_output,	// Output from the user program to the remote access module
 		output wire [3:0] four_bit_input,	// Input to the user program from the remote access module
 		input wire [7:0] eight_bit_output,	// Output from the user program to the remote access module
@@ -87,7 +89,7 @@
 	assign lcd_data_in_data = 8'b0;		// Disable LCD I/O for now
 
 	// Instantiate main remote access module
-	remote_access #(RAM_ADDR_BITS) remote_access(.main_fifty_clock(main_50_mhz_clock), .remote_access_4_bit_output(four_bit_output),
+	remote_access #(RAM_ADDR_BITS) remote_access(.main_fifty_clock(main_50_mhz_clock), .user_logic_reset(guest_logic_reset), .remote_access_4_bit_output(four_bit_output),
 		.remote_access_4_bit_input(four_bit_input), .remote_access_8_bit_output(eight_bit_output),
 		.remote_access_8_bit_input(eight_bit_input), .remote_access_16_bit_output(sixteen_bit_output),
 		.remote_access_16_bit_input(sixteen_bit_input),
f8f6ee88 2019-04-29 00:33:34 Timothy Pearson
Add test program for Lattice guest FPGAs
A fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile
A fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf
A fpga/serial/lattice/eb85/ice40_remotefpga_test/main.v

fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile

diff --git a/fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile b/fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile
new file mode 100644
index 0000000..04a0f2d
--- /dev/null
+++ b/fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile
@@ -0,0 +1,123 @@
+# This file is part of the Universal Laboratory (uLab)
+#
+# © 2017 - 2019 Raptor Engineering, LLC
+# All Rights Reserved
+#
+# Licensed under the terms of the AGPL v3
+
+MAX_FPGA_ROUTE_PASSES = 100
+
+SOURCE_FILES = main.v
+
+# Default seed
+#ARACHNE_PNR_SEED = 1
+
+# Selected seed from fastest placement search
+# NOTE: Must be updated every time the Verilog source is modified, no matter how trivially!
+# Does not need to be updated if firmware program (C) sources are modified
+# 0 automatically uses the best placement result
+ARACHNE_PNR_SEED = 0
+#ARACHNE_PNR_SEED = 1
+
+YOSYS_ICE40_SIM_LIB = $(shell yosys-config --datdir/ice40/cells_sim.v)
+
+.PRECIOUS: guest_fpga_%.int
+
+guest_fpga_%.tmg: guest_fpga_%.int guest_fpga.pcf
+	echo "Total path delay: inf ns (0.0 MHz)" > $@
+	-icetime -tmd hx8k -p guest_fpga.pcf -P ct256 $< > $@ 2>&1
+
+guest_fpga_%.int: guest_fpga.blif guest_fpga.pcf
+	echo "" > $@
+	-arachne-pnr -s $* -d 8k -P ct256 -m $(MAX_FPGA_ROUTE_PASSES) -p guest_fpga.pcf $< -o $@
+
+guest_fpga.int: guest_fpga_1.tmg guest_fpga_2.tmg guest_fpga_3.tmg guest_fpga_4.tmg guest_fpga_5.tmg guest_fpga_6.tmg guest_fpga_7.tmg guest_fpga_8.tmg guest_fpga_9.tmg \
+		guest_fpga_10.tmg guest_fpga_11.tmg guest_fpga_12.tmg guest_fpga_13.tmg guest_fpga_14.tmg guest_fpga_15.tmg guest_fpga_16.tmg guest_fpga_17.tmg guest_fpga_18.tmg guest_fpga_19.tmg \
+		guest_fpga_20.tmg guest_fpga_21.tmg guest_fpga_22.tmg guest_fpga_23.tmg guest_fpga_24.tmg guest_fpga_25.tmg guest_fpga_26.tmg guest_fpga_27.tmg guest_fpga_28.tmg guest_fpga_29.tmg \
+		guest_fpga_30.tmg guest_fpga_31.tmg guest_fpga_32.tmg guest_fpga_33.tmg guest_fpga_34.tmg guest_fpga_35.tmg guest_fpga_36.tmg guest_fpga_37.tmg guest_fpga_38.tmg guest_fpga_39.tmg \
+		guest_fpga_40.tmg guest_fpga_41.tmg guest_fpga_42.tmg guest_fpga_43.tmg guest_fpga_44.tmg guest_fpga_45.tmg guest_fpga_46.tmg guest_fpga_47.tmg guest_fpga_48.tmg guest_fpga_49.tmg \
+		guest_fpga_50.tmg guest_fpga_51.tmg guest_fpga_52.tmg guest_fpga_53.tmg guest_fpga_54.tmg guest_fpga_55.tmg guest_fpga_56.tmg guest_fpga_57.tmg guest_fpga_58.tmg guest_fpga_59.tmg \
+		guest_fpga_60.tmg guest_fpga_61.tmg guest_fpga_62.tmg guest_fpga_63.tmg guest_fpga_64.tmg
+	BEST_TRIAL=0;																														\
+	BEST_TRIAL_RESULT=0;																													\
+	for trial in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64; do							\
+		CURRENT_TRIAL_RESULT=$$(cat guest_fpga_$${trial}.tmg | grep "Total path delay" | awk '{print $$6}' | sed 's/(//g');																\
+		if [ "$$CURRENT_TRIAL_RESULT" != "" ]; then																									\
+			echo "guest_fpga_$${trial}.tmg : $$CURRENT_TRIAL_RESULT";																						\
+			COMPARISON_RESULT=$$(echo "$$CURRENT_TRIAL_RESULT > $$BEST_TRIAL_RESULT" | bc -l);																			\
+			if [ $$COMPARISON_RESULT -eq 1 ]; then																									\
+				BEST_TRIAL=guest_fpga_$${trial}.tmg;																								\
+				BEST_TRIAL_RESULT=$$CURRENT_TRIAL_RESULT;																							\
+			fi;																													\
+		fi;																														\
+	done;																															\
+	if [ "$$BEST_TRIAL_RESULT" -eq "0" ]; then																										\
+		echo "Unable to determine fastest result.  Selecting first run....";																						\
+		BEST_TRIAL=guest_fpga_1.tmg;																											\
+		BEST_TRIAL_RESULT=0;																												\
+	fi;																															\
+	echo "Fastest result: $$BEST_TRIAL : $$BEST_TRIAL_RESULT";																								\
+	cp `echo $$BEST_TRIAL | sed 's/\.tmg/\.int/g'` guest_fpga.int;																								\
+	cp $$BEST_TRIAL guest_fpga.tmg
+ifneq ($(ARACHNE_PNR_SEED),0)
+	cp guest_fpga_$(ARACHNE_PNR_SEED).int guest_fpga.int
+	cp guest_fpga_$(ARACHNE_PNR_SEED).tmg guest_fpga.tmg
+endif
+	cat guest_fpga.tmg
+
+guest_fpga.ex: guest_fpga.int
+	icebox_explain guest_fpga.int > guest_fpga.ex
+
+guest_fpga.blif: $(SOURCE_FILES)
+	yosys -l yosys.log -q -p "synth_ice40 -top guest_fpga_top -blif guest_fpga.blif" $(SOURCE_FILES)
+
+guest_fpga.bin: guest_fpga.int
+	icepack guest_fpga.int guest_fpga.bin
+
+blank.rom:
+	dd if=/dev/zero ibs=1k count=256 | tr "\000" "\377" > blank.rom
+
+guest_fpga.rom: blank.rom guest_fpga.bin
+	cp blank.rom guest_fpga.rom
+	dd if=guest_fpga.bin of=guest_fpga.rom conv=notrunc
+
+guest_fpga_test.vcd: $(SOURCE_FILES) testbench.v
+	rm -f guest_fpga_sim
+	rm -f guest_fpga.vcd
+	/usr/bin/iverilog -DSIMULATION -o guest_fpga_sim $(SOURCE_FILES) testbench.v
+	./guest_fpga_sim
+
+simulate: guest_fpga_test.vcd
+
+simulate_view: guest_fpga_test.vcd
+	gtkwave guest_fpga_test.vcd
+
+all: guest_fpga.rom
+
+dump_toolchain_info:
+	-@echo "================================================================================"
+	-@echo "Base system:\t"
+	-@echo -n "Architecture:\t"
+	-@uname -m 2>/dev/null
+	-@echo -n "gcc:\t\t"
+	-@gcc -dumpversion 2>/dev/null
+	-@echo -n "clang:\t\t"
+	-@clang --version 2>/dev/null | head -n 1
+	-@echo "\nFPGA toolchain:"
+	-@echo -n "Icarus verilog:\t"
+	-@iverilog -V 2>/dev/null | head -n 1
+	-@echo -n "Yosys:\t\t"
+	-@yosys -V 2>/dev/null
+	-@echo -n "arachne-pnr:\t"
+	-@arachne-pnr -v 2>/dev/null
+	-@echo "================================================================================"
+
+test: guest_fpga.bin
+	iceprog -S guest_fpga.bin
+
+flash: guest_fpga.bin
+	iceprog guest_fpga.bin
+
+clean:
+	rm -f guest_fpga.blif guest_fpga.ex guest_fpga.int guest_fpga.tmg guest_fpga_*.int guest_fpga_*.tmg guest_fpga.bin yosys.log
+

fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf

diff --git a/fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf b/fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf
new file mode 100644
index 0000000..00ee8d7
--- /dev/null
+++ b/fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf
@@ -0,0 +1,106 @@
+# This file is part of the Universal Laboratory (uLab)
+#
+# © 2017 - 2019 Raptor Engineering, LLC
+# All Rights Reserved
+#
+# Licensed under the terms of the AGPL v3
+
+# Main system clock
+set_io clk J3
+
+# Guest FPGA interface
+set_io reset A16
+
+set_io four_bit_output[3] C16
+set_io four_bit_output[2] D16
+set_io four_bit_output[1] E16
+set_io four_bit_output[0] F16
+
+set_io four_bit_input[3] B16
+set_io four_bit_input[2] D14
+set_io four_bit_input[1] D15
+set_io four_bit_input[0] E14
+
+set_io eight_bit_output[7] G16
+set_io eight_bit_output[6] H16
+set_io eight_bit_output[5] J15
+set_io eight_bit_output[4] G14
+set_io eight_bit_output[3] K14
+set_io eight_bit_output[2] K15
** Diff limit reached (max: 250 lines) **