diff --git a/flashSPI/Makefile b/flashSPI/Makefile new file mode 100644 index 0000000..3c9beb4 --- /dev/null +++ b/flashSPI/Makefile @@ -0,0 +1,14 @@ +PROJ = controller +DEVICE = 8k +FILES = controller.v + +.PHONY: all clean + +all: + yosys -p "synth_ice40 -top main -json $(PROJ).json" $(FILES) + nextpnr-ice40 -r --hx8k --json $(PROJ).json --package cb132 --asc $(PROJ).asc --opt-timing --pcf iceFUN.pcf + icepack $(PROJ).asc $(PROJ).bin + iceFUNprog $(PROJ).bin + +clean: + rm *.asc *.bin *blif *.out *.json *.history *.vcd .sconsign.dblite \ No newline at end of file diff --git a/flashSPI/README.md b/flashSPI/README.md new file mode 100644 index 0000000..3307f1d --- /dev/null +++ b/flashSPI/README.md @@ -0,0 +1,13 @@ +# Flash Read ID Operation + +This project directory contains an implimentation of the `Resume from Deep Power-Down and Read Device ID (ABh) ` operation initiated by the FPGA device on the iceFUN, to the [flash device](https://www.digikey.com/htmldatasheets/production/1568138/0/0/1/at25sf081-shd-t.html) on the iceFUN. + +# Use + +It is possible to install the necessary pre-requisites for compilation and testing from two sources: + +- [robot electronics webpage](https://www.robot-electronics.co.uk/icefun.html) + +- [apio](https://github.com/FPGAwars/apio) + +Once binary is flashed to the iceFUN, the leds will desplay the deviceID \ No newline at end of file diff --git a/flashSPI/apio.ini b/flashSPI/apio.ini new file mode 100644 index 0000000..f793e20 --- /dev/null +++ b/flashSPI/apio.ini @@ -0,0 +1,3 @@ +[env] +board = icefun +top-module = main \ No newline at end of file diff --git a/flashSPI/controller.v b/flashSPI/controller.v new file mode 100644 index 0000000..676c81f --- /dev/null +++ b/flashSPI/controller.v @@ -0,0 +1,61 @@ +/* + * + * Copyright(C) 2024 Kai Harris + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or + * without fee is hereby granted, provided that the above copyright notice and + * this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`include "sub_clock_module.v" +`include "flash_module.v" +`include "leds.v" + +module main ( + input clk, + input miso, + output cs, + output sck, + output mosi, + output [7:0] led, + output [3:0] col +); + + /*system wiring*/ + wire [7:0] flash_response; + wire sub_clock, SI_out_clock; + + /*clock module management*/ + sub_clock_module sub_clock_module ( + .top_clk(clk), + .sub_clock(sub_clock), + .SI_out_clock(SI_out_clock) + ); + + /*flash module management*/ + flash_module flash_module ( + .top_clk(sub_clock), + .sub_clk(SI_out_clock), + .miso(miso), + .cs(cs), + .sck(sck), + .mosi(mosi), + .flash_response(flash_response) + ); + + /*led module management*/ + led_module led_module ( + .led_set(flash_response), + .led(led), + .col(col) + ); + +endmodule \ No newline at end of file diff --git a/flashSPI/flash_module.v b/flashSPI/flash_module.v new file mode 100644 index 0000000..cc35e97 --- /dev/null +++ b/flashSPI/flash_module.v @@ -0,0 +1,107 @@ +/* + * + * Copyright(C) 2024 Kai Harris + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or + * without fee is hereby granted, provided that the above copyright notice and + * this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module flash_module( + input top_clk, + input sub_clk, + input miso, + output cs, + output sck, + output mosi, + output [7:0] flash_response +); + /*operation state*/ + parameter await_delay = 0; + parameter perform_op = 1; + reg clock_state; + + /*long gap between operations*/ + parameter OPERATION_DELAY = 14'b11111111111111; + reg [13:0] delay_counter; + + /*opcode*/ + parameter [31:0] OPCODE = {4'b1010, 4'b1011, 8'b0, 8'b0, 8'b0}; + + /*counters and flags*/ + integer operation_counter; + integer SI_pulse, SO_pulse; + reg clock_start_flag; + + /*module wiring*/ + reg CS_register, MOSI_register, SCK_register; + reg [7:0] FLASH_RESPONSE; + assign cs = CS_register; + assign sck = SCK_register; + assign mosi = MOSI_register; + assign flash_response = FLASH_RESPONSE; + + /*initialisation*/ + initial begin + clock_state <= await_delay; + delay_counter <= 0; + operation_counter <= 0; + SI_pulse <= 0; + clock_start_flag <= 0; + CS_register <= 1; + MOSI_register <= OPCODE[31]; + FLASH_RESPONSE <= 8'b11111111; + end + + /*CS, SI and SO control*/ + always @ (posedge sub_clk) begin + case (clock_state) + await_delay : begin + delay_counter <= delay_counter + 1; + if (delay_counter == OPERATION_DELAY - 1) begin + CS_register <= 0; + clock_state <= perform_op; + end + end + perform_op : begin + if (delay_counter == OPERATION_DELAY) begin + clock_start_flag <= 1; + end begin + operation_counter <= operation_counter + 1; + if (operation_counter <= 31) begin + SI_pulse <= SI_pulse + 1; + MOSI_register <= OPCODE[31-SI_pulse]; + end + if (operation_counter >= 31 && operation_counter < 39) begin + SO_pulse <= SO_pulse + 1; + FLASH_RESPONSE[7-SO_pulse] <= miso; + end + if (operation_counter == 39) begin + clock_state <= await_delay; + delay_counter <= 0; + operation_counter <= 0; + SI_pulse <= 0; + clock_start_flag <= 0; + MOSI_register <= OPCODE[31]; + CS_register <= 1; + end + end + end + endcase + end + + /*SCK wiring control*/ + always @ (*) begin + if (clock_start_flag) SCK_register <= top_clk; + else SCK_register <= 0; + end + +endmodule \ No newline at end of file diff --git a/flashSPI/iceFUN.pcf b/flashSPI/iceFUN.pcf new file mode 100644 index 0000000..86ba58f --- /dev/null +++ b/flashSPI/iceFUN.pcf @@ -0,0 +1,21 @@ +# Pinout defined by hardware vendor here: https://www.robot-electronics.co.uk/files/iceFUNdoc.pdf + +set_io --warn-no-port led[0] C10 +set_io --warn-no-port led[1] A10 +set_io --warn-no-port led[2] D7 +set_io --warn-no-port led[3] D6 +set_io --warn-no-port led[4] A7 +set_io --warn-no-port led[5] C7 +set_io --warn-no-port led[6] A4 +set_io --warn-no-port led[7] C4 +set_io --warn-no-port col[0] A12 +set_io --warn-no-port col[1] D10 +set_io --warn-no-port col[2] A6 +set_io --warn-no-port col[3] C5 + +set_io --warn-no-port clk P7 + +set_io --warn-no-port cs P13 +set_io --warn-no-port sck P12 +set_io --warn-no-port miso P11 +set_io --warn-no-port mosi M11 \ No newline at end of file diff --git a/flashSPI/leds.v b/flashSPI/leds.v new file mode 100644 index 0000000..8d90419 --- /dev/null +++ b/flashSPI/leds.v @@ -0,0 +1,40 @@ +/* + * + * Copyright(C) 2024 Kai Harris + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or + * without fee is hereby granted, provided that the above copyright notice and + * this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module led_module( + input [7:0] led_set, + output [7:0] led, + output [3:0] col +); + /*led module wiring*/ + reg [7:0] led_register; + reg [3:0] col_register; + assign led = led_register; + assign col = col_register; + + /*module initialisation*/ + initial begin + led_register <= 8'b11111111; + col_register <= 4'b1110; + end + + /*set leds*/ + always @(*) begin + led_register <= led_set; + end + +endmodule diff --git a/flashSPI/output_tb.v b/flashSPI/output_tb.v new file mode 100644 index 0000000..508c671 --- /dev/null +++ b/flashSPI/output_tb.v @@ -0,0 +1,49 @@ +/* + * + * Copyright(C) 2024 Kai Harris + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or + * without fee is hereby granted, provided that the above copyright notice and + * this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps // Time scale directive, 1 ns time unit, 1 ps time precision + +module output_tb(); + wire cs, sck, mosi; + reg clk = 0; + + localparam CLK_PERIOD = 83.33; // 12 MHz clock -> 1/12_000_000 second period -> 83.33 nanosecons + localparam HALF_CLK_PERIOD = 41.67; + localparam DURATION = 1000000; + + main uut ( + .clk(clk), + .cs(cs), + .sck(sck), + .mosi(mosi) + ); + + // VCD dump for waveform analysis + initial begin + $dumpfile("output_tb.vcd"); // Create VCD file for simulation waveform output + $dumpvars(0, output_tb); // Dump variables from top module (output_tb) + #(DURATION); // Run simulation for specified duration + $finish; // End the simulation + end + + // Clock generation block + always begin + #(HALF_CLK_PERIOD) // Half-period delay + clk = ~clk; // Toggle clock signal every half period + end + +endmodule diff --git a/flashSPI/sub_clock_module.v b/flashSPI/sub_clock_module.v new file mode 100644 index 0000000..0f84ed5 --- /dev/null +++ b/flashSPI/sub_clock_module.v @@ -0,0 +1,74 @@ +/* + * + * Copyright(C) 2024 Kai Harris + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with or + * without fee is hereby granted, provided that the above copyright notice and + * this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +module sub_clock_module( + input top_clk, + output sub_clock, + output SI_out_clock +); + + /*output clock hyperparameters*/ + parameter LOW = 0; + parameter HIGH = 1; + parameter HIGH_COUNT = 2; + parameter LOW_COUNT = 20; + parameter LOW_COUNT_RISING = 15; + + /*counters*/ + integer high_counter; + integer low_counter; + + /*module wiring*/ + reg clock_state_active, SI_out_reg; + assign sub_clock = clock_state_active; + assign SI_out_clock = SI_out_reg; + + /*module initialisation*/ + initial begin + clock_state_active <= LOW; + SI_out_reg <= 1; + high_counter <= 0; + low_counter <= 0; + end + + /*output clock signal management*/ + always @(posedge top_clk) begin + case (clock_state_active) + LOW : begin + if (low_counter < LOW_COUNT) low_counter <= low_counter + 1; + if (low_counter == LOW_COUNT) begin + clock_state_active <= HIGH; + low_counter <= 0; + end + if (low_counter == LOW_COUNT_RISING) begin + SI_out_reg <= 1; + end + if (low_counter != LOW_COUNT_RISING) begin + SI_out_reg <= 0; + end + end + HIGH : begin + if (high_counter == HIGH_COUNT) begin + clock_state_active <= LOW; + high_counter <= 0; + end + else high_counter <= high_counter + 1; + end + endcase + end + +endmodule