added a tested flash module for performing the read-id operation

This commit is contained in:
alien flip
2024-11-04 10:15:18 +00:00
parent 2abb4c7aa9
commit 964befb841
8 changed files with 408 additions and 0 deletions

View File

@@ -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

View File

@@ -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`

View File

@@ -0,0 +1,3 @@
[env]
board = iCESugar_1_5
top-module = main

View File

@@ -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

View File

@@ -0,0 +1,117 @@
/*
*
* Copyright(C) 2024 Kai Harris <matchahack@gmail.com>
*
* 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

View File

@@ -0,0 +1,127 @@
/*
*
* Copyright(C) 2024 Kai Harris <matchahack@gmail.com>
*
* 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

View File

@@ -0,0 +1,49 @@
/*
*
* Copyright(C) 2024 Kai Harris <matchahack@gmail.com>
*
* 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

View File

@@ -0,0 +1,78 @@
/*
*
* Copyright(C) 2024 Kai Harris <matchahack@gmail.com>
*
* 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