diff --git a/fpga/serial/common/remote_access.v b/fpga/serial/common/remote_access.v index 3a52885..e30006f 100644 --- a/fpga/serial/common/remote_access.v +++ b/fpga/serial/common/remote_access.v @@ -18,6 +18,9 @@ // sales@raptorengineering.com // ////////////////////////////////////////////////////////////////////////////////// + +`include "remote_access_defines.v" + module remote_access( input main_fifty_clock, // 50MHz clock in input [3:0] remote_access_4_bit_output, // 4 bit output from the user program to remote access client @@ -38,13 +41,17 @@ module remote_access( input [5:0] lcd_data_in_address, input [7:0] lcd_data_in_data, input lcd_data_in_enable, +`ifdef SYSTEM_HAS_SRAM input sram_wren_in, input sram_clock_in, input [7:0] sram_data_in, input [(RAM_ADDR_BITS-1):0] sram_address_in, output [7:0] sram_data_out, +`endif output sram_available, +`ifdef SYSTEM_HAS_SRAM input sram_processing_done, +`endif input [7:0] led_segment_bus, input [3:0] led_digit_select, @@ -55,6 +62,10 @@ module remote_access( output remote_access_lcd_enable_out); parameter RAM_ADDR_BITS = 14; + +`ifndef SYSTEM_HAS_SRAM + reg sram_processing_done = 1'b1; +`endif reg [7:0] remote_access_4_bit_input_reg; reg [7:0] remote_access_8_bit_input_reg; @@ -184,7 +195,7 @@ module remote_access( led_display_bytes[3] = 255; end end - + //----------------------------------------------------------------------------------- // // Instantiate the data storage RAM for signal processing @@ -202,6 +213,7 @@ module remote_access( reg [(RAM_ADDR_BITS-1):0] data_storage_addra_reg; reg data_storage_write_enable_reg; +`ifdef SYSTEM_HAS_SRAM data_storage #(RAM_ADDR_BITS) data_storage(.clka(data_storage_clka), .dina(data_storage_dina), .addra(data_storage_addra), .wea(data_storage_write_enable), .douta(data_storage_data_out)); @@ -211,6 +223,7 @@ module remote_access( assign data_storage_write_enable = (data_storage_remote_enable) ? data_storage_write_enable_reg : sram_wren_in; assign sram_data_out = data_storage_data_out; +`endif // ----------------------------------------------------------------------------------------------- // @@ -396,11 +409,17 @@ module remote_access( if ((transmit_dsp_status == 1) && (transmit_dsp_rx_complete == 0) && (transmit_dsp_status_done == 0)) begin if (transmit_dsp_status_holdoff == 0) begin transmit_dsp_status_holdoff = 1; +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 0; data_storage_addra_reg = 0; // Initial data value +`endif end else begin +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 0; TxD_data = data_storage_data_out; +`else + TxD_data = 0; +`endif TxD_start = 1; tx_toggle = 1; @@ -409,8 +428,10 @@ module remote_access( data_storage_addra_reg = transmit_dsp_status_counter[(RAM_ADDR_BITS-1):0]; if (transmit_dsp_status_counter >= (2**RAM_ADDR_BITS)) begin transmit_dsp_status_done = 1; +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 1'bz; data_storage_addra_reg = {(RAM_ADDR_BITS){1'bz}}; +`endif end end end @@ -581,7 +602,9 @@ module remote_access( data_write_timer = data_write_timer - 1; end else begin if (data_write_timer == 1) begin +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 0; +`endif data_write_timer = 0; end end @@ -607,9 +630,11 @@ module remote_access( // DSP input data if (dsp_update_counter < (2**RAM_ADDR_BITS)) begin data_storage_remote_enable = 1; +`ifdef SYSTEM_HAS_SRAM data_storage_addra_reg = dsp_update_counter[(RAM_ADDR_BITS-1):0]; data_storage_dina_reg = serial_rx_data_reg; data_storage_write_enable_reg = 1; +`endif data_write_timer = 3; dsp_update_counter = dsp_update_counter + 1; @@ -620,11 +645,15 @@ module remote_access( if (dsp_update_counter >= (2**RAM_ADDR_BITS)) begin next_byte_is_command = 0; +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 0; +`endif data_storage_remote_enable = 0; sram_available_reg = 1; +`ifdef SYSTEM_HAS_SRAM data_storage_write_enable_reg = 1'bz; data_storage_addra_reg = {(RAM_ADDR_BITS){1'bz}}; +`endif waiting_on_dsp_processing = 1; transmit_dsp_rx_complete = 1; next_byte_is_command_prev_command = 0; diff --git a/fpga/serial/lattice/eb85/Makefile b/fpga/serial/lattice/eb85/Makefile new file mode 100644 index 0000000..d00e5a5 --- /dev/null +++ b/fpga/serial/lattice/eb85/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 remote_access.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: control_fpga_%.int + +control_fpga_%.tmg: control_fpga_%.int control_fpga.pcf + echo "Total path delay: inf ns (0.0 MHz)" > $@ + -icetime -tmd hx8k -p control_fpga.pcf -P ct256 $< > $@ 2>&1 + +control_fpga_%.int: control_fpga.blif control_fpga.pcf + echo "" > $@ + -arachne-pnr -s $* -d 8k -P ct256 -m $(MAX_FPGA_ROUTE_PASSES) -p control_fpga.pcf $< -o $@ + +control_fpga.int: control_fpga_1.tmg control_fpga_2.tmg control_fpga_3.tmg control_fpga_4.tmg control_fpga_5.tmg control_fpga_6.tmg control_fpga_7.tmg control_fpga_8.tmg control_fpga_9.tmg \ + control_fpga_10.tmg control_fpga_11.tmg control_fpga_12.tmg control_fpga_13.tmg control_fpga_14.tmg control_fpga_15.tmg control_fpga_16.tmg control_fpga_17.tmg control_fpga_18.tmg control_fpga_19.tmg \ + control_fpga_20.tmg control_fpga_21.tmg control_fpga_22.tmg control_fpga_23.tmg control_fpga_24.tmg control_fpga_25.tmg control_fpga_26.tmg control_fpga_27.tmg control_fpga_28.tmg control_fpga_29.tmg \ + control_fpga_30.tmg control_fpga_31.tmg control_fpga_32.tmg control_fpga_33.tmg control_fpga_34.tmg control_fpga_35.tmg control_fpga_36.tmg control_fpga_37.tmg control_fpga_38.tmg control_fpga_39.tmg \ + control_fpga_40.tmg control_fpga_41.tmg control_fpga_42.tmg control_fpga_43.tmg control_fpga_44.tmg control_fpga_45.tmg control_fpga_46.tmg control_fpga_47.tmg control_fpga_48.tmg control_fpga_49.tmg \ + control_fpga_50.tmg control_fpga_51.tmg control_fpga_52.tmg control_fpga_53.tmg control_fpga_54.tmg control_fpga_55.tmg control_fpga_56.tmg control_fpga_57.tmg control_fpga_58.tmg control_fpga_59.tmg \ + control_fpga_60.tmg control_fpga_61.tmg control_fpga_62.tmg control_fpga_63.tmg control_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 control_fpga_$${trial}.tmg | grep "Total path delay" | awk '{print $$6}' | sed 's/(//g'); \ + if [ "$$CURRENT_TRIAL_RESULT" != "" ]; then \ + echo "control_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=control_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=control_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'` control_fpga.int; \ + cp $$BEST_TRIAL control_fpga.tmg +ifneq ($(ARACHNE_PNR_SEED),0) + cp control_fpga_$(ARACHNE_PNR_SEED).int control_fpga.int + cp control_fpga_$(ARACHNE_PNR_SEED).tmg control_fpga.tmg +endif + cat control_fpga.tmg + +control_fpga.ex: control_fpga.int + icebox_explain control_fpga.int > control_fpga.ex + +control_fpga.blif: $(SOURCE_FILES) + yosys -l yosys.log -q -p "synth_ice40 -top control_fpga_top -blif control_fpga.blif" $(SOURCE_FILES) + +control_fpga.bin: control_fpga.int + icepack control_fpga.int control_fpga.bin + +blank.rom: + dd if=/dev/zero ibs=1k count=256 | tr "\000" "\377" > blank.rom + +control_fpga.rom: blank.rom control_fpga.bin + cp blank.rom control_fpga.rom + dd if=control_fpga.bin of=control_fpga.rom conv=notrunc + +control_fpga_test.vcd: $(SOURCE_FILES) testbench.v + rm -f control_fpga_sim + rm -f control_fpga.vcd + /usr/bin/iverilog -DSIMULATION -o control_fpga_sim $(SOURCE_FILES) testbench.v + ./control_fpga_sim + +simulate: control_fpga_test.vcd + +simulate_view: control_fpga_test.vcd + gtkwave control_fpga_test.vcd + +all: control_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: control_fpga.bin + iceprog -S control_fpga.bin + +flash: control_fpga.bin + iceprog control_fpga.bin + +clean: + rm -f control_fpga.blif control_fpga.ex control_fpga.int control_fpga.tmg control_fpga_*.int control_fpga_*.tmg control_fpga.bin yosys.log + diff --git a/fpga/serial/lattice/eb85/control_fpga.pcf b/fpga/serial/lattice/eb85/control_fpga.pcf new file mode 100644 index 0000000..ddcaaa2 --- /dev/null +++ b/fpga/serial/lattice/eb85/control_fpga.pcf @@ -0,0 +1,66 @@ +# 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 main_12_mhz_clock J3 + +# Debug / GPIO connections +set_io led_bank[7] C3 +set_io led_bank[6] B3 +set_io led_bank[5] C4 +set_io led_bank[4] C5 +set_io led_bank[3] A1 +set_io led_bank[2] A2 +set_io led_bank[1] B4 +set_io led_bank[0] B5 + +# Guest FPGA interface +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 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 + +# Serial interface +set_io serial_input B10 +set_io serial_output B12 diff --git a/fpga/serial/lattice/eb85/main.v b/fpga/serial/lattice/eb85/main.v new file mode 100644 index 0000000..e736781 --- /dev/null +++ b/fpga/serial/lattice/eb85/main.v @@ -0,0 +1,98 @@ +// 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 + +module control_fpga_top + ( + // Input clock + input wire main_12_mhz_clock, + + // Guest FPGA interface + 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 + output wire [7:0] eight_bit_input, // Input to the user program from the remote access module + + input wire [7:0] led_segment_bus, + input wire [3:0] led_digit_select, + + // Serial interface + input wire serial_input, + output wire serial_output, + + // On-board diagnostic LEDs + output wire [7:0] led_bank + ); + + parameter RAM_ADDR_BITS = 0; + + // Synthesize 50MHz clock from 12MHz clock + wire main_50_mhz_clock; + wire pll_locked; + + SB_PLL40_CORE #( + .FEEDBACK_PATH("SIMPLE"), + .DIVR(4'b0000), // DIVR = 0 + .DIVF(7'b1000010), // DIVF = 66 + .DIVQ(3'b100), // DIVQ = 4 + .FILTER_RANGE(3'b001) // FILTER_RANGE = 1 + ) system_pll ( + .LOCK(pll_locked), + .RESETB(1'b1), + .BYPASS(1'b0), + .REFERENCECLK(main_12_mhz_clock), + .PLLOUTCORE(main_50_mhz_clock) + ); + + reg [7:0] diagnostic_led_data = 8'b0; + + wire [15:0] sixteen_bit_output; // Output from the user program to the remote access module + wire [15:0] sixteen_bit_input; // Input to the user program from the remote access module + + wire [5:0] lcd_data_in_address; + wire [7:0] lcd_data_in_data; + wire lcd_data_in_enable; + + assign sixteen_bit_output = 16'b0; // Diable 16 bit input for now + //assign led_bank = eight_bit_input; // Mirror input to the LEDs + assign led_bank = diagnostic_led_data; // Show diagnostic data on LEDs + + reg [22:0] slow_clock_divider = 23'b0; + wire slow_clock; + reg [1:0] kr_state = 2'b0; + always @(posedge main_12_mhz_clock) begin + slow_clock_divider <= slow_clock_divider + 1; + end + assign slow_clock = slow_clock_divider[22]; + + always @(posedge slow_clock) begin + kr_state <= kr_state + 1; + if (pll_locked) begin + case (kr_state) + 0: diagnostic_led_data <= 8'b00011000; + 1: diagnostic_led_data <= 8'b00100100; + 2: diagnostic_led_data <= 8'b01000010; + 3: diagnostic_led_data <= 8'b10000001; + endcase + end else begin + diagnostic_led_data <= 8'b0; + end + end + + assign lcd_data_in_enable = 1'b0; // Disable LCD I/O for now + assign lcd_data_in_address = 6'b0; // Disable LCD I/O for now + 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_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), + .serial_port_receiver(serial_input), .serial_port_transmitter(serial_output), .remote_access_input_enable(1'b0), + .local_input(8'b0), .seize_serial_tx(1'b0), .serial_tx_data(8'b0), .serial_tx_strobe(1'b0), + .lcd_data_in_address(lcd_data_in_address), .lcd_data_in_data(lcd_data_in_data), .lcd_data_in_enable(lcd_data_in_enable), + .led_segment_bus(led_segment_bus), .led_digit_select(led_digit_select)); +endmodule diff --git a/fpga/serial/lattice/eb85/remote_access.v b/fpga/serial/lattice/eb85/remote_access.v new file mode 120000 index 0000000..2d26470 --- /dev/null +++ b/fpga/serial/lattice/eb85/remote_access.v @@ -0,0 +1 @@ +../../common/remote_access.v \ No newline at end of file diff --git a/fpga/serial/lattice/eb85/remote_access_defines.v b/fpga/serial/lattice/eb85/remote_access_defines.v new file mode 100644 index 0000000..a9948fd --- /dev/null +++ b/fpga/serial/lattice/eb85/remote_access_defines.v @@ -0,0 +1,8 @@ +// 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 + +// `define SYSTEM_HAS_SRAM 1 diff --git a/fpga/serial/xilinx/digilent/spartan_3/remote_access_defines.v b/fpga/serial/xilinx/digilent/spartan_3/remote_access_defines.v new file mode 100644 index 0000000..63792f0 --- /dev/null +++ b/fpga/serial/xilinx/digilent/spartan_3/remote_access_defines.v @@ -0,0 +1,8 @@ +// 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 + +`define SYSTEM_HAS_SRAM 1 diff --git a/fpga/serial/xilinx/digilent/spartan_3e/remote_access_defines.v b/fpga/serial/xilinx/digilent/spartan_3e/remote_access_defines.v new file mode 100644 index 0000000..63792f0 --- /dev/null +++ b/fpga/serial/xilinx/digilent/spartan_3e/remote_access_defines.v @@ -0,0 +1,8 @@ +// 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 + +`define SYSTEM_HAS_SRAM 1 diff --git a/fpga/serial/xilinx/digilent/spartan_6/remote_access_defines.v b/fpga/serial/xilinx/digilent/spartan_6/remote_access_defines.v new file mode 100644 index 0000000..63792f0 --- /dev/null +++ b/fpga/serial/xilinx/digilent/spartan_6/remote_access_defines.v @@ -0,0 +1,8 @@ +// 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 + +`define SYSTEM_HAS_SRAM 1