From 964befb841ffd4bbbb62e92914bd073cba453978 Mon Sep 17 00:00:00 2001 From: alien flip Date: Mon, 4 Nov 2024 10:15:18 +0000 Subject: [PATCH] added a tested flash module for performing the read-id operation --- src/basic/verilog/flash_icesugar/Makefile | 19 +++ src/basic/verilog/flash_icesugar/README.md | 7 + src/basic/verilog/flash_icesugar/apio.ini | 3 + .../verilog/flash_icesugar/common/io.pcf | 8 ++ src/basic/verilog/flash_icesugar/control.v | 117 ++++++++++++++++ .../verilog/flash_icesugar/flash_module.v | 127 ++++++++++++++++++ src/basic/verilog/flash_icesugar/output_tb.v | 49 +++++++ .../verilog/flash_icesugar/sub_clock_module.v | 78 +++++++++++ 8 files changed, 408 insertions(+) create mode 100644 src/basic/verilog/flash_icesugar/Makefile create mode 100644 src/basic/verilog/flash_icesugar/README.md create mode 100644 src/basic/verilog/flash_icesugar/apio.ini create mode 100644 src/basic/verilog/flash_icesugar/common/io.pcf create mode 100644 src/basic/verilog/flash_icesugar/control.v create mode 100644 src/basic/verilog/flash_icesugar/flash_module.v create mode 100644 src/basic/verilog/flash_icesugar/output_tb.v create mode 100644 src/basic/verilog/flash_icesugar/sub_clock_module.v diff --git a/src/basic/verilog/flash_icesugar/Makefile b/src/basic/verilog/flash_icesugar/Makefile new file mode 100644 index 0000000..4e099c6 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/Makefile @@ -0,0 +1,19 @@ +filename = control +pcf_file = common/io.pcf + +clean: + rm .sconsign.dblite *.out *.vcd + +build: + yosys -p "synth_ice40 -json bin/$(filename).json" $(filename).v + nextpnr-ice40 \ + --up5k \ + --package sg48 \ + --json bin/$(filename).json \ + --pcf $(pcf_file) \ + --asc bin/$(filename).asc + icepack bin/$(filename).asc bin/$(filename).bin + +sim: + apio sim + make clean diff --git a/src/basic/verilog/flash_icesugar/README.md b/src/basic/verilog/flash_icesugar/README.md new file mode 100644 index 0000000..0e56455 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/README.md @@ -0,0 +1,7 @@ +# flash_icesugar + +In this directory, the user can compile and test using either `apio` (in which case, they can also output the simulation files), or with the standard Lattice OS toolchain + +When compiled, the user should observe that the `MISO` line responds with the Manufacturer ID - hex `EF` (as noted in the W25Q64F flash [docs](https://www.pjrc.com/store/w25q64fv.pdf) in section 6.2.30), followed by the Device ID + +This directory is tested and verified as working on the `icesugar v1.5` diff --git a/src/basic/verilog/flash_icesugar/apio.ini b/src/basic/verilog/flash_icesugar/apio.ini new file mode 100644 index 0000000..26c7439 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/apio.ini @@ -0,0 +1,3 @@ +[env] +board = iCESugar_1_5 +top-module = main \ No newline at end of file diff --git a/src/basic/verilog/flash_icesugar/common/io.pcf b/src/basic/verilog/flash_icesugar/common/io.pcf new file mode 100644 index 0000000..d249a64 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/common/io.pcf @@ -0,0 +1,8 @@ +# For the iCESugar Board (iCE40UP5K-QFN48) + +set_io --warn-no-port clk 35 + +set_io --warn-no-port cs 16 +set_io --warn-no-port sck 15 +set_io --warn-no-port mosi 14 +set_io --warn-no-port miso 17 diff --git a/src/basic/verilog/flash_icesugar/control.v b/src/basic/verilog/flash_icesugar/control.v new file mode 100644 index 0000000..5a3731c --- /dev/null +++ b/src/basic/verilog/flash_icesugar/control.v @@ -0,0 +1,117 @@ +/* + * + * 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" + +module main ( + input clk, + input miso, + output cs, + output sck, + output mosi +); + /*system wiring*/ + reg flash_start; + wire flash_done; + wire sub_clock, SI_out_clock; + + wire [1023:0] SO_data; + reg [1055:0] SI_data; + reg [11:0] SI_len; + reg [11:0] SO_len; + reg [11:0] OP_end; + + /*device states*/ + reg [3:0] DEVICE_STATE; + parameter RESUME_PREP = 4'b0000; + parameter RESUME = 4'b0001; + parameter READ_ID_PREP = 4'b0010; + parameter READ_ID = 4'b0100; + parameter DEFAULT = 4'b1000; + + initial begin + SI_data <= 0; + SI_len <= 0; + SO_len <= 0; + OP_end <= 0; + flash_start <= 0; + DEVICE_STATE <= RESUME_PREP; + end + + always @ (posedge clk) begin + case (DEVICE_STATE) + RESUME_PREP : begin + SI_data[7:0] <= {8'hAB}; // opcode for RESUME + SI_len <= 12'b000000000111; // 7 + SO_len <= 12'b000000000000; // 0 + OP_end <= 12'b000000001000; // 8 + DEVICE_STATE <= RESUME; + end + RESUME : begin + if (flash_done == 0) flash_start <= 1; + if (flash_done == 1 && flash_start == 1) begin + flash_start <= 0; + SI_data <= 0; + DEVICE_STATE <= READ_ID_PREP; + end + end + READ_ID_PREP : begin + SI_data[31:0] <= {8'h90, 24'h000000}; // opcode for Read Device ID + SI_len <= 12'b000000011111; // 31 + SO_len <= 12'b000000001111; // 15 + OP_end <= 12'b000000110000; // 48 + DEVICE_STATE <= READ_ID; + end + READ_ID : begin + if (flash_done == 0) flash_start <= 1; + if (flash_done == 1 && flash_start == 1) begin + flash_start <= 0; + SI_data <= 0; + DEVICE_STATE <= READ_ID_PREP; + end + end + DEFAULT: begin + end + endcase + end + + /*flash_modules*/ + flash_module flash_module ( + .top_clk(sub_clock), + .sub_clk(SI_out_clock), + .flash_start(flash_start), + .SI_data(SI_data), + .SI_len(SI_len), + .SO_len(SO_len), + .OP_end(OP_end), + .miso(miso), + .cs(cs), + .sck(sck), + .mosi(mosi), + .SO_data(SO_data), + .flash_done(flash_done) + ); + + /*clock module management*/ + sub_clock_module sub_clock_module ( + .top_clk(clk), + .sub_clock(sub_clock), + .SI_out_clock(SI_out_clock) + ); + +endmodule \ No newline at end of file diff --git a/src/basic/verilog/flash_icesugar/flash_module.v b/src/basic/verilog/flash_icesugar/flash_module.v new file mode 100644 index 0000000..1e6dc07 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/flash_module.v @@ -0,0 +1,127 @@ +/* + * + * 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. + * + */ + +`ifndef FLASH_MODULE_V // Check if FLASH_MODULE_V is not defined +`define FLASH_MODULE_V // Define FLASH_MODULE_V + +module flash_module( + input top_clk, + input sub_clk, + input flash_start, + input [1055:0] SI_data, + input [11:0] SI_len, + input [11:0] SO_len, + input [11:0] OP_end, + input miso, + output cs, + output sck, + output mosi, + output [1023:0] SO_data, + output flash_done +); + /*module wiring*/ + reg CS_register, MOSI_register, SCK_register; + reg [1023:0] SO_register; + assign cs = CS_register; + assign sck = SCK_register; + assign mosi = MOSI_register; + assign SO_data = SO_register; + + /*operation state*/ + parameter await_delay = 0; + parameter perform_op = 1; + reg clock_state, clock_start_flag, flash_done_register; + assign flash_done = flash_done_register; + + /*operation delay*/ + parameter OPERATION_DELAY = 4'b1111; + reg [3:0] delay_counter; + + /*counters and flags*/ + integer operation_counter, SI_pulse, SO_pulse; + + /*initialisation*/ + initial begin + clock_state <= await_delay; + delay_counter <= 0; + operation_counter <= 0; + SI_pulse <= 0; + SO_pulse <= 0; + clock_start_flag <= 0; + CS_register <= 1; + flash_done_register <= 0; + end + + /*CS, SI and SO control*/ + always @ (posedge sub_clk) begin + if (delay_counter == 0) flash_done_register <= 0; + if (flash_start == 1 && flash_done_register == 0) 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; + MOSI_register <= SI_data[SI_len]; + end + end + perform_op : begin + if (delay_counter == OPERATION_DELAY) begin + clock_start_flag <= 1; + end begin + operation_counter <= operation_counter + 1; + if (SO_len == 0) begin + if (operation_counter <= SI_len) begin + SI_pulse <= SI_pulse + 1; + MOSI_register <= SI_data[SI_len - SI_pulse]; + end + end + if (SO_len != 0) begin + if (operation_counter <= SI_len) begin + SI_pulse <= SI_pulse + 1; + MOSI_register <= SI_data[SI_len - SI_pulse]; + end + if (operation_counter > SI_len && operation_counter < OP_end) begin + SO_pulse <= SO_pulse + 1; + SO_register[SO_len - SO_pulse] <= miso; + end + end + if (operation_counter == OP_end) begin + clock_state <= await_delay; + delay_counter <= 0; + operation_counter <= 0; + SI_pulse <= 0; + clock_start_flag <= 0; + MOSI_register <= SI_data[SI_len]; + CS_register <= 1; + flash_done_register <= 1; + end + end + end + endcase + end + end + + /*SCK wiring control*/ + always @ (*) begin + if (clock_start_flag == 1) SCK_register <= top_clk; + else SCK_register <= 0; + end + +endmodule + +`endif \ No newline at end of file diff --git a/src/basic/verilog/flash_icesugar/output_tb.v b/src/basic/verilog/flash_icesugar/output_tb.v new file mode 100644 index 0000000..c259a10 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/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 = 100000; + + 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/src/basic/verilog/flash_icesugar/sub_clock_module.v b/src/basic/verilog/flash_icesugar/sub_clock_module.v new file mode 100644 index 0000000..2e75776 --- /dev/null +++ b/src/basic/verilog/flash_icesugar/sub_clock_module.v @@ -0,0 +1,78 @@ +/* + * + * 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. + * + */ + +`ifndef SUB_CLOCK_MODULE_V // Check if SUB_CLOCK_MODULE_V is not defined +`define SUB_CLOCK_MODULE_V // Define SUB_CLOCK_MODULE_V + +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 = 4; + parameter LOW_COUNT_RISING = 2; + + /*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 + +`endif