summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineering.com>2019-04-28 19:33:34 -0500
committerTimothy Pearson <tpearson@raptorengineering.com>2019-04-28 19:33:34 -0500
commitf8f6ee88d8738be66558f32eb1dd21da955b1111 (patch)
treed9ec93cdc0ff7324ced4c8968ecf9fc9116acebc
parentcd7e1ea3b8f89ccc65ced6003a653cf831d92ab8 (diff)
downloadulab-f8f6ee88d8738be66558f32eb1dd21da955b1111.tar.gz
ulab-f8f6ee88d8738be66558f32eb1dd21da955b1111.zip
Add test program for Lattice guest FPGAs
-rw-r--r--fpga/serial/lattice/eb85/ice40_remotefpga_test/Makefile123
-rw-r--r--fpga/serial/lattice/eb85/ice40_remotefpga_test/guest_fpga.pcf106
-rw-r--r--fpga/serial/lattice/eb85/ice40_remotefpga_test/main.v104
3 files changed, 333 insertions, 0 deletions
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
+
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
+set_io eight_bit_output[1] M16
+set_io eight_bit_output[0] N16
+
+set_io eight_bit_input[7] F15
+set_io eight_bit_input[6] G15
+set_io eight_bit_input[5] H14
+set_io eight_bit_input[4] F14
+set_io eight_bit_input[3] J14
+set_io eight_bit_input[2] K16
+set_io eight_bit_input[1] L16
+set_io eight_bit_input[0] M15
+
+set_io sixteen_bit_output[15] B1
+set_io sixteen_bit_output[14] C1
+set_io sixteen_bit_output[13] D1
+set_io sixteen_bit_output[12] E2
+set_io sixteen_bit_output[11] F2
+set_io sixteen_bit_output[10] G2
+set_io sixteen_bit_output[9] H2
+set_io sixteen_bit_output[8] J2
+set_io sixteen_bit_output[7] K3
+set_io sixteen_bit_output[6] L3
+set_io sixteen_bit_output[5] M2
+set_io sixteen_bit_output[4] N3
+set_io sixteen_bit_output[3] P1
+set_io sixteen_bit_output[2] B12
+set_io sixteen_bit_output[1] B13
+set_io sixteen_bit_output[0] A15
+
+set_io sixteen_bit_input[15] B2
+set_io sixteen_bit_input[14] C2
+set_io sixteen_bit_input[13] D2
+set_io sixteen_bit_input[12] F1
+set_io sixteen_bit_input[11] G1
+set_io sixteen_bit_input[10] H1
+set_io sixteen_bit_input[9] R1
+set_io sixteen_bit_input[8] J1
+set_io sixteen_bit_input[7] K1
+set_io sixteen_bit_input[6] L1
+set_io sixteen_bit_input[5] M1
+set_io sixteen_bit_input[4] N2
+set_io sixteen_bit_input[3] P2
+set_io sixteen_bit_input[2] B11
+set_io sixteen_bit_input[1] B14
+set_io sixteen_bit_input[0] B15
+
+set_io lcd_data_in_address[5] T11
+set_io lcd_data_in_address[4] N10
+set_io lcd_data_in_address[3] N12
+set_io lcd_data_in_address[2] T13
+set_io lcd_data_in_address[1] T15
+set_io lcd_data_in_address[0] R16
+
+set_io lcd_data_in_data[7] R6
+set_io lcd_data_in_data[6] T8
+set_io lcd_data_in_data[5] R9
+set_io lcd_data_in_data[4] P9
+set_io lcd_data_in_data[3] R10
+set_io lcd_data_in_data[2] P10
+set_io lcd_data_in_data[1] M11
+set_io lcd_data_in_data[0] P13
+
+set_io lcd_data_in_enable T14
+
+set_io led_segment_bus[7] T1
+set_io led_segment_bus[6] R2
+set_io led_segment_bus[5] R3
+set_io led_segment_bus[4] T5
+set_io led_segment_bus[3] T6
+set_io led_segment_bus[2] T7
+set_io led_segment_bus[1] P8
+set_io led_segment_bus[0] T10
+
+set_io led_digit_select[3] T2
+set_io led_digit_select[2] T3
+set_io led_digit_select[1] R4
+set_io led_digit_select[0] R5
diff --git a/fpga/serial/lattice/eb85/ice40_remotefpga_test/main.v b/fpga/serial/lattice/eb85/ice40_remotefpga_test/main.v
new file mode 100644
index 0000000..3c7fa0f
--- /dev/null
+++ b/fpga/serial/lattice/eb85/ice40_remotefpga_test/main.v
@@ -0,0 +1,104 @@
+// This file is part of the Universal Laboratory (uLab)
+//
+// © 2007 - 2019 Raptor Engineering, LLC
+// All Rights Reserved
+//
+// Licensed under the terms of the AGPL v3
+
+module guest_fpga_top(clk, reset, four_bit_input, four_bit_output, eight_bit_input, eight_bit_output, sixteen_bit_input, sixteen_bit_output, lcd_data_in_address, lcd_data_in_data, lcd_data_in_enable, led_segment_bus, led_digit_select);
+ input clk;
+ input reset;
+
+ input [3:0] four_bit_input;
+ output reg [3:0] four_bit_output;
+ input [7:0] eight_bit_input;
+ output reg [7:0] eight_bit_output;
+ input [15:0] sixteen_bit_input;
+ output reg [15:0] sixteen_bit_output;
+
+ output reg [5:0] lcd_data_in_address;
+ output reg [7:0] lcd_data_in_data;
+ output reg lcd_data_in_enable;
+
+ output reg [7:0] led_segment_bus;
+ output reg [3:0] led_digit_select;
+
+ reg [7:0] lcd_sample_counter = 48; // Create a sample LCD display counter register
+ reg [31:0] lcd_character_change_timer = 0; // Wait a certain number of cycles before loading a new character
+ reg [5:0] lcd_current_character = 0; // The current character's address
+
+ always @(posedge clk) begin
+ four_bit_output = four_bit_input; // Loopback
+ eight_bit_output = eight_bit_input[3:0] + eight_bit_input[7:4]; // Sample adder
+ sixteen_bit_output = sixteen_bit_input[15:8] * sixteen_bit_input[7:0]; // Sample multiplier
+
+ // Sample LCD display routine
+ lcd_data_in_address = lcd_current_character; // Character location on the LCD display
+ lcd_data_in_data = lcd_sample_counter; // Character code to display
+ lcd_data_in_enable = 1; // Enable data transmission
+
+ // Cycle through all character positions
+ lcd_current_character = lcd_current_character + 1;
+ if (lcd_current_character > 31) begin
+ lcd_current_character = 16;
+ end
+
+ // Cycle through the numbers 0 to 9 at one second intervals
+ lcd_character_change_timer = lcd_character_change_timer + 1;
+ if (lcd_character_change_timer > 6000000) begin // Wait one second in between character changes
+ lcd_character_change_timer = 0;
+ lcd_sample_counter = lcd_sample_counter + 1;
+ if (lcd_sample_counter > 57) begin // Character code for the digit 9
+ lcd_sample_counter = 48; // Character code for the digit 0
+ end
+ end
+ end
+
+ // 7-segment LED display driver clock generator
+ reg sseg_clock;
+ reg [4:0] sseg_clock_counter;
+
+ always @(posedge clk) begin
+ sseg_clock_counter = sseg_clock_counter + 1;
+ if (sseg_clock_counter > 16) begin
+ sseg_clock_counter = 0;
+ sseg_clock = ~sseg_clock;
+ end
+ end
+
+ // 7-segment LED display driver
+ // led_segment_bus and led_digit_select are active low
+ // The bit sequence, MSB to LSB, is dp a b c d e f g
+ // Segment letters are taken from ug130.pdf page 15
+
+ // 0: 8'b10000001
+ // 1: 8'b11001111
+ // 2: 8'b10010010
+ // 3: 8'b10000110
+ reg [2:0] current_anode;
+ always @(posedge sseg_clock) begin
+ current_anode = current_anode + 1;
+ if (current_anode > 3) begin
+ current_anode = 0;
+ end
+
+ case (current_anode)
+ 0: begin
+ led_digit_select = 4'b1110;
+ led_segment_bus = 8'b10000001;
+ end
+ 1: begin
+ led_digit_select = 4'b1101;
+ led_segment_bus = 8'b11001111;
+ end
+ 2: begin
+ led_digit_select = 4'b1011;
+ led_segment_bus = 8'b10010010;
+ end
+ 3: begin
+ led_digit_select = 4'b0111;
+ led_segment_bus = 8'b10000110;
+ end
+ endcase
+ end
+endmodule