aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-11-03 19:16:12 +0100
committerWojciech Kosior <kwojtus@protonmail.com>2020-11-03 19:16:12 +0100
commitcd0c787bcfc89a0a1e14f4404a59cb4697854621 (patch)
treeea96fd360441b7c6f171b642016b68039283cc8a /models
parent33f05839b7815a5a18a2b920dba4549d2bd7ce16 (diff)
downloadAGH-engineering-thesis-cd0c787bcfc89a0a1e14f4404a59cb4697854621.tar.gz
AGH-engineering-thesis-cd0c787bcfc89a0a1e14f4404a59cb4697854621.zip
add spi wishbone slave with a simplified flash memory chip model and a test bench
Diffstat (limited to 'models')
-rw-r--r--models/flash_memory.v206
1 files changed, 206 insertions, 0 deletions
diff --git a/models/flash_memory.v b/models/flash_memory.v
new file mode 100644
index 0000000..3b6c659
--- /dev/null
+++ b/models/flash_memory.v
@@ -0,0 +1,206 @@
+`default_nettype none
+`timescale 1ns/1ns
+
+`include "messages.vh"
+
+`ifndef SIMULATION
+ `error_SIMULATION_not_defined
+; /* Cause syntax error */
+`endif
+
+module W25Q16BV_flash
+ #(
+ parameter BYTES_TO_INITIALIZE = 0,
+ parameter INITIAL_CONTENTS_FILE = "some_file.mem"
+ )
+ (
+ /* wires we're not using are omitted */
+ input wire sdo,
+ output wire sdi,
+ input wire sck,
+ input wire ss_n
+ );
+
+ reg outputting;
+ initial
+ outputting <= 0;
+ reg outputted_bit;
+ assign sdi = (outputting && !ss_n) ? outputted_bit : 1'bz;
+
+ reg powered_up;
+ initial
+ powered_up <= 0;
+
+ reg powering_up_in_progress;
+ initial
+ powering_up_in_progress <= 0;
+
+ parameter power_up_wait_time = 3000; /* ns */
+ integer power_up_time;
+
+ parameter idle = 0;
+ parameter error = 1;
+ parameter receiving_instruction = 2;
+ parameter releasing_power_down = 3;
+ parameter receiving_fast_read_address = 4;
+ parameter receiving_fast_read_dummy_byte = 5;
+ parameter responding_fast_read = 6;
+ integer state;
+ initial
+ state <= idle;
+
+ parameter release_power_down_instruction = 8'hAB;
+ parameter fast_read_instruction = 8'h0B;
+
+ reg [7:0] instruction;
+ integer instruction_bits_received;
+
+ reg [23:0] address;
+ integer address_bits_received;
+ reg [2:0] bit_in_byte;
+
+ integer dummy_bits_received;
+
+ parameter memory_size = 1024 * 1024 * 2; /* 2 megabytes */
+ reg [7:0] memory [memory_size - 1 : 0];
+ initial
+ $readmemh(INITIAL_CONTENTS_FILE, memory, 0, BYTES_TO_INITIALIZE - 1);
+
+ always @ (posedge sck) begin
+ if (!powered_up && power_up_time + power_up_wait_time < $time) begin
+ powered_up <= 1;
+ if (state == releasing_power_down)
+ state = idle;
+ end
+
+ case (state)
+ idle : begin
+ if (!ss_n) begin
+ state <= receiving_instruction;
+ instruction_bits_received <= 1;
+ instruction[7] <= sdo;
+ end
+ end
+ error : begin
+ if (ss_n) begin
+ state <= idle;
+ end
+ end
+ receiving_instruction : begin
+ if (ss_n) begin
+ state <= idle;
+ `MSG(("SPI: error: operation aborted after only %0d instruction bits received",
+ instruction_bits_received));
+ end else begin
+ instruction[7 - instruction_bits_received] <= sdo;
+ instruction_bits_received <= instruction_bits_received + 1;
+
+ if (instruction_bits_received + 1 == 8) begin
+ if (!powered_up && ({instruction[7:1], sdo} !=
+ release_power_down_instruction)) begin
+ state <= error;
+ `MSG(("SPI: error: attempted instruction 0x%x while in power down mode",
+ {instruction[7:1], sdo}));
+ end else begin
+ case ({instruction[7:1], sdo})
+ release_power_down_instruction : begin
+ state <= releasing_power_down;
+ power_up_time <= $time;
+ `DBG(("SPI: release power down issued"));
+ end
+ fast_read_instruction : begin
+ state <= receiving_fast_read_address;
+ address_bits_received <= 0;
+ `DBG(("SPI: fast read issued"));
+ end
+ default : begin
+ state <= error;
+ `MSG(("SPI: error: unknown instruction: 0x%x",
+ {instruction[7:1], sdo}));
+ end
+ endcase // case ({instruction[7:1], sdo})
+ end // else: !if(!powered_up && ({instruction[7:1], sdo} !=...
+ end // if (instruction_bits_received + 1 == 8)
+ end // else: !if(ss_n)
+ end // case: receiving_instruction
+ releasing_power_down : begin
+ if (!ss_n) begin
+ state <= receiving_instruction;
+ instruction_bits_received <= 1;
+ instruction[7] <= sdo;
+
+ if (power_up_time + power_up_wait_time >= $time) begin
+ `MSG(("SPI: error: release power down interrupted %0d ns before finishing",
+ power_up_time + power_up_wait_time - $time));
+ end
+ end // if (!ss_n)
+ end // case: releasing_power_down
+ receiving_fast_read_address : begin
+ if (ss_n) begin
+ state <= idle;
+ `MSG(("SPI: error: fast read instruction aborted after %0d bits of address were sent",
+ address_bits_received));
+ end else begin
+ address[23 - address_bits_received] <= sdo;
+ address_bits_received <= address_bits_received + 1;
+
+ if (address_bits_received + 1 == 24) begin
+ state <= receiving_fast_read_dummy_byte;
+ dummy_bits_received <= 0;
+ end
+ end
+ end
+ receiving_fast_read_dummy_byte : begin
+ if (ss_n) begin
+ state <= idle;
+ `MSG(("SPI: error: fast read instruction aborted after %0d bits of dummy byte were sent",
+ dummy_bits_received));
+ end else begin
+ dummy_bits_received <= dummy_bits_received + 1;
+
+ if (dummy_bits_received + 1 == 8) begin
+ bit_in_byte <= 7;
+
+ if (address >= memory_size) begin
+ state <= error;
+ `MSG(("SPI: error: memory address too high (0x%x)",
+ address));
+ end else begin
+ state <= responding_fast_read;
+ end
+ end
+ end // else: !if(ss_n)
+ end // case: receiving_fast_read_dummy_byte
+ responding_fast_read : begin
+ if (ss_n) begin
+ state <= idle;
+ end else begin
+ bit_in_byte <= bit_in_byte - 1;
+
+ if (bit_in_byte == 0) begin
+ address <= address + 1;
+
+ if (address + 1 >= memory_size) begin
+ state <= error;
+ `MSG(("SPI: error: memory address too high (0x%x)",
+ address));
+ end
+ end
+ end // else: !if(ss_n)
+ end // case: responding_fast_read
+ endcase // case (state)
+ end // always @ (posedge sck)
+
+ always @ (negedge sck) begin
+ if (ss_n) begin
+ outputting <= 0;
+ end else if (state == responding_fast_read) begin
+ outputting <= 1;
+ outputted_bit <= memory[address][bit_in_byte];
+ end else if (state == error) begin
+ outputted_bit <= 1'bx;
+ end else begin
+ outputting <= 0;
+ end
+ end // always @ (negedge sck)
+endmodule // W25Q16BV_flash