From 84929109347cb80b980c5c7751a27923573b5e99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 03:02:11 +0000 Subject: [PATCH 1/4] Initial plan From 99dd17e7e2425ba415055ebf770731a6ea49bf74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 03:07:28 +0000 Subject: [PATCH 2/4] Add comprehensive NAND vs NOR flash memory documentation and examples Co-authored-by: ewdlop <25368970+ewdlop@users.noreply.github.com> --- Misc/Flash-Memory/README.md | 464 ++++++++++++++++++++++ Misc/Flash-Memory/nand_flash_controller.v | 310 +++++++++++++++ Misc/Flash-Memory/nor_flash_controller.v | 137 +++++++ 3 files changed, 911 insertions(+) create mode 100644 Misc/Flash-Memory/README.md create mode 100644 Misc/Flash-Memory/nand_flash_controller.v create mode 100644 Misc/Flash-Memory/nor_flash_controller.v diff --git a/Misc/Flash-Memory/README.md b/Misc/Flash-Memory/README.md new file mode 100644 index 0000000..cb61d81 --- /dev/null +++ b/Misc/Flash-Memory/README.md @@ -0,0 +1,464 @@ +# NAND vs. NOR Flash Memory + +Flash memory is a type of non-volatile storage technology that retains data even when power is removed. The two primary types of flash memory are **NAND** and **NOR** flash, named after their respective logic gate structures. Each has distinct characteristics that make them suitable for different applications. + +--- + +## **1. Architecture Overview** + +### **NOR Flash** +- **Cell Structure**: NOR flash cells are connected in parallel, similar to a NOR gate configuration +- **Bit Organization**: Each cell can be individually accessed +- **Interface**: Provides a memory-mapped interface with individual address lines +- **Architecture Type**: Random access architecture + +### **NAND Flash** +- **Cell Structure**: NAND flash cells are connected in series, similar to a NAND gate configuration +- **Bit Organization**: Cells are organized into pages (typically 2KB-16KB) and blocks +- **Interface**: Requires I/O interface with sequential access +- **Architecture Type**: Serial access architecture with page-based operations + +--- + +## **2. Key Characteristics Comparison** + +| Feature | NOR Flash | NAND Flash | +|---------|-----------|------------| +| **Read Speed** | Very Fast (5-50 ns) | Slower (25 μs per page) | +| **Write Speed** | Slow (5-10 μs per byte) | Fast (200-700 μs per page) | +| **Erase Speed** | Very Slow (1 second per block) | Fast (2-3 ms per block) | +| **Density** | Lower (up to 256 Mb typical) | Higher (up to several TB) | +| **Cost per Bit** | Higher | Lower (3-4x cheaper) | +| **Interface** | Parallel/Random Access | Serial/Page Access | +| **Execute-in-Place (XiP)** | Yes | No | +| **Endurance** | 10,000-100,000 cycles | 3,000-100,000 cycles | +| **Bad Blocks** | Rare | Common (requires management) | +| **Power Consumption** | Higher | Lower | + +--- + +## **3. Memory Organization** + +### **NOR Flash Memory Structure** +``` +┌─────────────────────────────────┐ +│ Address Bus (A0-An) │ +├─────────────────────────────────┤ +│ │ +│ Individual Memory Cells │ +│ ┌──┬──┬──┬──┬──┬──┬──┬──┐ │ +│ │C0│C1│C2│C3│C4│C5│C6│C7│ │ +│ └──┴──┴──┴──┴──┴──┴──┴──┘ │ +│ │ +│ Random Access Interface │ +│ │ +├─────────────────────────────────┤ +│ Data Bus (D0-D7/D15) │ +└─────────────────────────────────┘ +``` + +**Characteristics:** +- Direct addressing of individual bytes +- Similar interface to traditional SRAM/DRAM +- Suitable for code execution (XiP - Execute in Place) + +### **NAND Flash Memory Structure** +``` +┌─────────────────────────────────┐ +│ I/O Interface │ +├─────────────────────────────────┤ +│ │ +│ Page (e.g., 2KB) │ +│ ┌────────────────────────┐ │ +│ │ Block (e.g., 64 pages)│ │ +│ │ ┌──┬──┬──┬──┬──┐ │ │ +│ │ │P0│P1│P2│...│Pn│ │ │ +│ │ └──┴──┴──┴──┴──┘ │ │ +│ └────────────────────────┘ │ +│ │ +│ Multiple Blocks Form Array │ +│ │ +├─────────────────────────────────┤ +│ Command/Data Register │ +└─────────────────────────────────┘ +``` + +**Characteristics:** +- Page-based read/write operations +- Block-based erase operations +- Requires page buffering for random access +- Not suitable for direct code execution + +--- + +## **4. Access Mechanisms** + +### **NOR Flash Access** +1. **Read Operation**: + - Direct byte/word access + - Similar to reading from RAM + - Fast random access + ``` + Address → Data (immediate) + ``` + +2. **Write Operation**: + - Byte-by-byte programming + - Requires erase before write + - Slow compared to read + ``` + 1. Issue write command + 2. Provide address + 3. Write data + 4. Wait for completion + ``` + +3. **Erase Operation**: + - Sector or chip erase + - Very slow process + - Required before writing + +### **NAND Flash Access** +1. **Read Operation**: + - Page-based sequential read + - Transfer entire page to buffer + - Then access data from buffer + ``` + 1. Issue read command + 2. Provide page address + 3. Wait for page load (~25μs) + 4. Read data from buffer + ``` + +2. **Write Operation**: + - Page programming + - Faster than NOR + - Sequential write to page + ``` + 1. Issue program command + 2. Load data to page buffer + 3. Provide page address + 4. Execute program (~200-700μs) + ``` + +3. **Erase Operation**: + - Block erase + - Faster than NOR + - Larger granularity + +--- + +## **5. Performance Characteristics** + +### **Read Performance** +- **NOR**: Excellent for random access + - 5-50 ns access time + - Ideal for code execution + - No buffering required + +- **NAND**: Better for sequential access + - Initial latency: ~25 μs + - Sequential throughput: 20-40 MB/s + - Requires buffering for random access + +### **Write Performance** +- **NOR**: Slow + - 5-10 μs per byte + - Limited by programming mechanism + - Suitable for small, infrequent updates + +- **NAND**: Fast + - 200-700 μs per page + - Higher throughput for large writes + - Better for data storage applications + +### **Erase Performance** +- **NOR**: Very slow + - 1-5 seconds per sector + - Limits write throughput + - Large erase granularity + +- **NAND**: Relatively fast + - 2-3 ms per block + - Enables better write performance + - More efficient for frequent updates + +--- + +## **6. Use Cases and Applications** + +### **NOR Flash Applications** +✓ **Code Storage and Execution** + - BIOS/Firmware storage + - Embedded system boot code + - Microcontroller program memory + +✓ **Small Data Storage with Frequent Reads** + - Configuration data + - Lookup tables + - Calibration parameters + +✓ **Real-Time Systems** + - Automotive ECUs + - Industrial controllers + - Network equipment + +**Example Applications:** +- Router firmware +- Automotive engine controllers +- Set-top box boot code +- IoT device firmware +- FPGA configuration storage + +### **NAND Flash Applications** +✓ **Mass Data Storage** + - USB flash drives + - Solid-state drives (SSDs) + - Memory cards (SD, microSD) + - Embedded MultiMediaCard (eMMC) + +✓ **High-Capacity Requirements** + - Digital cameras + - Smartphones + - Tablets + - Media players + +✓ **Sequential Data Access** + - Data logging + - Audio/video recording + - File systems + +**Example Applications:** +- Smartphone storage +- Digital camera storage +- USB thumb drives +- Laptop SSDs +- Embedded storage in tablets + +--- + +## **7. Technical Implementation Details** + +### **NOR Flash Interface Example** +```verilog +// Typical NOR Flash Interface Signals +input [ADDR_WIDTH-1:0] address; // Direct address lines +inout [DATA_WIDTH-1:0] data; // Bidirectional data bus +input we_n; // Write enable (active low) +input oe_n; // Output enable (active low) +input ce_n; // Chip enable (active low) +input rst_n; // Reset (active low) +output ready; // Ready/Busy indicator +``` + +**Access Pattern:** +- Memory-mapped interface +- Similar to SRAM timing +- Direct CPU execution possible + +### **NAND Flash Interface Example** +```verilog +// Typical NAND Flash Interface Signals +inout [7:0] io; // Multiplexed I/O bus +input cle; // Command latch enable +input ale; // Address latch enable +input ce_n; // Chip enable (active low) +input we_n; // Write enable (active low) +input re_n; // Read enable (active low) +output rb_n; // Ready/Busy (active low) +input wp_n; // Write protect (active low) +``` + +**Access Pattern:** +- Command/address/data multiplexed +- Requires state machine for control +- Page buffering necessary + +--- + +## **8. Reliability and Endurance** + +### **NOR Flash Reliability** +- **Endurance**: 10,000 to 100,000 program/erase cycles +- **Data Retention**: 10-20 years +- **Error Rate**: Very low +- **Bad Blocks**: Extremely rare at manufacturing +- **Error Correction**: Usually not required + +### **NAND Flash Reliability** +- **Endurance**: + - SLC (Single-Level Cell): 50,000-100,000 cycles + - MLC (Multi-Level Cell): 3,000-10,000 cycles + - TLC (Triple-Level Cell): 1,000-3,000 cycles + - QLC (Quad-Level Cell): 500-1,000 cycles +- **Data Retention**: 1-10 years (depends on type) +- **Error Rate**: Higher than NOR +- **Bad Blocks**: Common (1-2% at manufacturing) +- **Error Correction**: ECC required (BCH, LDPC) + +--- + +## **9. Cell Technology Types** + +### **NOR Flash Cell Types** +1. **Standard NOR** + - Higher reliability + - Lower density + - Used in critical applications + +### **NAND Flash Cell Types** +1. **SLC (Single-Level Cell)** + - 1 bit per cell + - Highest performance and endurance + - Most expensive + - Used in enterprise applications + +2. **MLC (Multi-Level Cell)** + - 2 bits per cell + - Good balance of performance and cost + - Used in consumer SSDs + +3. **TLC (Triple-Level Cell)** + - 3 bits per cell + - Higher density, lower cost + - Used in consumer storage + +4. **QLC (Quad-Level Cell)** + - 4 bits per cell + - Highest density, lowest cost + - Lower endurance and performance + - Used in high-capacity storage + +--- + +## **10. Cost and Density Considerations** + +### **Cost Analysis** +- **NOR Flash**: + - Higher cost per bit (~4x NAND) + - Lower density + - More expensive manufacturing + - Suitable for low-capacity applications + +- **NAND Flash**: + - Lower cost per bit + - Higher density + - Economies of scale + - Suitable for mass storage + +### **Density Trends** +- **NOR**: Typically 128 Mb to 1 Gb +- **NAND**: + - Consumer: Up to 2 TB per chip + - 3D NAND: Stacked layers for even higher density + - Future: Moving towards QLC and PLC (Penta-Level Cell) + +--- + +## **11. Power Consumption** + +### **NOR Flash Power** +- **Active Read**: 20-50 mA (typical) +- **Active Write**: 30-100 mA +- **Standby**: 10-100 μA +- **Deep Power-Down**: 1-10 μA + +### **NAND Flash Power** +- **Active Read**: 10-30 mA (typical) +- **Active Write**: 15-50 mA +- **Standby**: 1-50 μA +- **Deep Power-Down**: <1 μA + +**Note**: NAND generally consumes less power, making it better for battery-powered devices. + +--- + +## **12. Design Considerations** + +### **When to Choose NOR Flash** +✓ Code storage and execution requirements +✓ Fast random read access needed +✓ Small capacity requirements (< 128 MB) +✓ High reliability critical +✓ Execute-in-Place (XiP) required +✓ Simple interface preferred + +### **When to Choose NAND Flash** +✓ High-capacity storage required (> 128 MB) +✓ Cost-sensitive applications +✓ Sequential access patterns +✓ Data storage rather than code +✓ Power consumption critical +✓ Write-intensive applications + +--- + +## **13. Future Trends** + +### **NOR Flash Evolution** +- Continued use in embedded systems +- Adoption of serial interfaces (SPI, Quad SPI) +- Smaller process nodes +- Increased density (but still limited vs. NAND) + +### **NAND Flash Evolution** +- **3D NAND**: Vertical stacking for higher density +- **QLC/PLC**: More bits per cell +- **Advanced ECC**: Improved error correction +- **NVMe**: Faster interfaces +- **Computational Storage**: Processing near storage + +--- + +## **14. Hybrid Approaches** + +Some modern systems use both types: +- **NOR** for boot code and critical firmware +- **NAND** for mass data storage and file systems + +**Example Architecture:** +``` +┌──────────────────────────────────────┐ +│ System-on-Chip (SoC) │ +│ │ +│ ┌────────────┐ ┌──────────────┐ │ +│ │ CPU │ │ Controller │ │ +│ └────────────┘ └──────────────┘ │ +│ │ │ │ +└─────────┼──────────────────┼─────────┘ + │ │ + ┌─────┴─────┐ ┌────┴────┐ + │ NOR Flash │ │ NAND │ + │ (Boot/FW) │ │ (Data) │ + └───────────┘ └─────────┘ + Fast Boot Mass Storage +``` + +--- + +## **15. Summary Table** + +| Aspect | NOR Flash | NAND Flash | +|--------|-----------|------------| +| **Best For** | Code execution, firmware | Data storage, mass storage | +| **Speed** | Fast read, slow write | Moderate read, fast write | +| **Capacity** | Low to medium | High to very high | +| **Cost** | Higher | Lower | +| **Interface** | Simple, memory-mapped | Complex, requires controller | +| **Reliability** | High | Medium (requires ECC) | +| **Power** | Higher | Lower | +| **Endurance** | High | Varies by type | +| **Random Access** | Excellent | Poor | +| **Sequential Access** | Good | Excellent | + +--- + +## **Conclusion** + +The choice between NAND and NOR flash memory depends on the specific application requirements: + +- **Use NOR** when you need fast random access, code execution capabilities, and high reliability for small amounts of data. + +- **Use NAND** when you need high-capacity storage, cost-effectiveness, and can accommodate a more complex interface with sequential access patterns. + +In many modern embedded systems, a combination of both technologies provides the best balance of performance, capacity, and cost. diff --git a/Misc/Flash-Memory/nand_flash_controller.v b/Misc/Flash-Memory/nand_flash_controller.v new file mode 100644 index 0000000..fd19d6e --- /dev/null +++ b/Misc/Flash-Memory/nand_flash_controller.v @@ -0,0 +1,310 @@ +// NAND Flash Memory Controller +// Provides page-based interface to NAND flash memory +// Supports page read, page program, and block erase operations + +module nand_flash_controller #( + parameter ADDR_WIDTH = 24, // Address width for page addressing + parameter DATA_WIDTH = 8, // I/O data width (typically 8-bit) + parameter PAGE_SIZE = 2048, // Page size in bytes + parameter PAGES_PER_BLOCK = 64, // Typical pages per block + parameter SPARE_SIZE = 64 // Spare/OOB area size +)( + input wire clk, + input wire rst_n, + + // Host Interface + input wire [ADDR_WIDTH-1:0] host_page_addr, + input wire [15:0] host_byte_addr, + input wire [DATA_WIDTH-1:0] host_data_in, + output reg [DATA_WIDTH-1:0] host_data_out, + input wire host_read_page, + input wire host_write_page, + input wire host_erase_block, + input wire host_read_id, + output reg host_ready, + output reg host_error, + + // NAND Flash Interface (8-bit I/O) + inout wire [7:0] flash_io, + output reg flash_cle, // Command latch enable + output reg flash_ale, // Address latch enable + output reg flash_ce_n, // Chip enable (active low) + output reg flash_we_n, // Write enable (active low) + output reg flash_re_n, // Read enable (active low) + input wire flash_rb_n, // Ready/Busy (active low) + output reg flash_wp_n // Write protect (active low) +); + + // NAND Flash Commands + localparam CMD_READ_1ST = 8'h00; + localparam CMD_READ_2ND = 8'h30; + localparam CMD_READ_ID = 8'h90; + localparam CMD_RESET = 8'hFF; + localparam CMD_PAGE_PROGRAM_1 = 8'h80; + localparam CMD_PAGE_PROGRAM_2 = 8'h10; + localparam CMD_BLOCK_ERASE_1 = 8'h60; + localparam CMD_BLOCK_ERASE_2 = 8'hD0; + localparam CMD_READ_STATUS = 8'h70; + + // State machine states + localparam IDLE = 4'd0; + localparam READ_CMD1 = 4'd1; + localparam READ_ADDR = 4'd2; + localparam READ_CMD2 = 4'd3; + localparam READ_WAIT = 4'd4; + localparam READ_DATA = 4'd5; + localparam WRITE_CMD1 = 4'd6; + localparam WRITE_ADDR = 4'd7; + localparam WRITE_DATA = 4'd8; + localparam WRITE_CMD2 = 4'd9; + localparam ERASE_CMD1 = 4'd10; + localparam ERASE_ADDR = 4'd11; + localparam ERASE_CMD2 = 4'd12; + localparam WAIT_READY = 4'd13; + localparam READ_STATUS_STATE = 4'd14; + + reg [3:0] state, next_state; + reg [7:0] io_out; + reg io_dir; // 0 = input from flash, 1 = output to flash + reg [3:0] addr_cycle; + reg [15:0] byte_counter; + reg [7:0] status_reg; + + // Bidirectional I/O control + assign flash_io = io_dir ? io_out : 8'hzz; + + // Page buffer (simplified - in real implementation would be larger) + reg [DATA_WIDTH-1:0] page_buffer [0:PAGE_SIZE-1]; + + // State machine - sequential logic + always @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + state <= IDLE; + addr_cycle <= 4'd0; + byte_counter <= 16'd0; + end else begin + state <= next_state; + + // Address cycle counter + if (state == READ_ADDR || state == WRITE_ADDR || state == ERASE_ADDR) begin + addr_cycle <= addr_cycle + 1'b1; + end else begin + addr_cycle <= 4'd0; + end + + // Byte counter for data transfer + if (state == READ_DATA || state == WRITE_DATA) begin + byte_counter <= byte_counter + 1'b1; + end else begin + byte_counter <= 16'd0; + end + end + end + + // State machine - combinational logic + always @(*) begin + // Default values + next_state = state; + flash_cle = 1'b0; + flash_ale = 1'b0; + flash_ce_n = 1'b1; + flash_we_n = 1'b1; + flash_re_n = 1'b1; + flash_wp_n = 1'b1; // Write protect off + io_dir = 1'b0; + io_out = 8'h00; + host_ready = 1'b0; + host_error = 1'b0; + host_data_out = 8'h00; + + case (state) + IDLE: begin + host_ready = 1'b1; + flash_ce_n = 1'b0; + + if (host_read_page) begin + next_state = READ_CMD1; + end else if (host_write_page) begin + next_state = WRITE_CMD1; + end else if (host_erase_block) begin + next_state = ERASE_CMD1; + end + end + + // === Page Read Sequence === + READ_CMD1: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_READ_1ST; + next_state = READ_ADDR; + end + + READ_ADDR: begin + flash_ce_n = 1'b0; + flash_ale = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + + // Send 5 address cycles (column addr + row addr) + case (addr_cycle) + 4'd0: io_out = host_byte_addr[7:0]; // Column address byte 1 + 4'd1: io_out = host_byte_addr[15:8]; // Column address byte 2 + 4'd2: io_out = host_page_addr[7:0]; // Row address byte 1 + 4'd3: io_out = host_page_addr[15:8]; // Row address byte 2 + 4'd4: begin + io_out = host_page_addr[23:16]; // Row address byte 3 + next_state = READ_CMD2; + end + default: io_out = 8'h00; + endcase + end + + READ_CMD2: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_READ_2ND; + next_state = READ_WAIT; + end + + READ_WAIT: begin + flash_ce_n = 1'b0; + // Wait for R/B# to go high (operation complete) + if (flash_rb_n == 1'b1) begin + next_state = READ_DATA; + end + end + + READ_DATA: begin + flash_ce_n = 1'b0; + flash_re_n = 1'b0; + host_data_out = flash_io; + + if (byte_counter >= PAGE_SIZE - 1) begin + next_state = IDLE; + end + end + + // === Page Program Sequence === + WRITE_CMD1: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_PAGE_PROGRAM_1; + next_state = WRITE_ADDR; + end + + WRITE_ADDR: begin + flash_ce_n = 1'b0; + flash_ale = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + + case (addr_cycle) + 4'd0: io_out = host_byte_addr[7:0]; + 4'd1: io_out = host_byte_addr[15:8]; + 4'd2: io_out = host_page_addr[7:0]; + 4'd3: io_out = host_page_addr[15:8]; + 4'd4: begin + io_out = host_page_addr[23:16]; + next_state = WRITE_DATA; + end + default: io_out = 8'h00; + endcase + end + + WRITE_DATA: begin + flash_ce_n = 1'b0; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = host_data_in; + + if (byte_counter >= PAGE_SIZE - 1) begin + next_state = WRITE_CMD2; + end + end + + WRITE_CMD2: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_PAGE_PROGRAM_2; + next_state = WAIT_READY; + end + + // === Block Erase Sequence === + ERASE_CMD1: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_BLOCK_ERASE_1; + next_state = ERASE_ADDR; + end + + ERASE_ADDR: begin + flash_ce_n = 1'b0; + flash_ale = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + + // Send 3 row address cycles for block erase + case (addr_cycle) + 4'd0: io_out = host_page_addr[7:0]; + 4'd1: io_out = host_page_addr[15:8]; + 4'd2: begin + io_out = host_page_addr[23:16]; + next_state = ERASE_CMD2; + end + default: io_out = 8'h00; + endcase + end + + ERASE_CMD2: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_BLOCK_ERASE_2; + next_state = WAIT_READY; + end + + // === Wait for operation completion === + WAIT_READY: begin + flash_ce_n = 1'b0; + if (flash_rb_n == 1'b1) begin + next_state = READ_STATUS_STATE; + end + end + + READ_STATUS_STATE: begin + flash_ce_n = 1'b0; + flash_cle = 1'b1; + flash_we_n = 1'b0; + io_dir = 1'b1; + io_out = CMD_READ_STATUS; + + // Read status register + flash_re_n = 1'b0; + status_reg = flash_io; + + // Check for errors (bit 0 indicates pass/fail) + if (status_reg[0] == 1'b1) begin + host_error = 1'b1; + end + + next_state = IDLE; + end + + default: begin + next_state = IDLE; + end + endcase + end + +endmodule diff --git a/Misc/Flash-Memory/nor_flash_controller.v b/Misc/Flash-Memory/nor_flash_controller.v new file mode 100644 index 0000000..75102e7 --- /dev/null +++ b/Misc/Flash-Memory/nor_flash_controller.v @@ -0,0 +1,137 @@ +// NOR Flash Memory Controller +// Provides a simple interface to NOR flash memory with memory-mapped access +// Supports read, write, and erase operations + +module nor_flash_controller #( + parameter ADDR_WIDTH = 20, // 1 MB addressable space + parameter DATA_WIDTH = 16, // 16-bit data bus + parameter SECTOR_SIZE = 65536 // 64KB sector size +)( + input wire clk, + input wire rst_n, + + // Processor Interface + input wire [ADDR_WIDTH-1:0] cpu_addr, + input wire [DATA_WIDTH-1:0] cpu_data_in, + output reg [DATA_WIDTH-1:0] cpu_data_out, + input wire cpu_read, + input wire cpu_write, + input wire cpu_erase_sector, + output reg cpu_ready, + + // NOR Flash Interface + output reg [ADDR_WIDTH-1:0] flash_addr, + inout wire [DATA_WIDTH-1:0] flash_data, + output reg flash_ce_n, // Chip enable (active low) + output reg flash_oe_n, // Output enable (active low) + output reg flash_we_n, // Write enable (active low) + output reg flash_rst_n, // Reset (active low) + input wire flash_ready // Ready/Busy from flash +); + + // State machine states + localparam IDLE = 3'b000; + localparam READ = 3'b001; + localparam WRITE_CMD = 3'b010; + localparam WRITE_DATA = 3'b011; + localparam ERASE_CMD = 3'b100; + localparam WAIT_READY = 3'b101; + + reg [2:0] state, next_state; + reg [DATA_WIDTH-1:0] data_out_reg; + reg data_dir; // 0 = input from flash, 1 = output to flash + + // Command codes for NOR flash + localparam CMD_READ = 16'h00FF; + localparam CMD_WRITE = 16'h0040; + localparam CMD_ERASE = 16'h0020; + localparam CMD_CONFIRM = 16'h00D0; + localparam CMD_STATUS = 16'h0070; + + // Bidirectional data bus control + assign flash_data = data_dir ? data_out_reg : {DATA_WIDTH{1'bz}}; + + // State machine + always @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + state <= IDLE; + end else begin + state <= next_state; + end + end + + // Next state logic and control signals + always @(*) begin + // Default values + next_state = state; + flash_ce_n = 1'b1; + flash_oe_n = 1'b1; + flash_we_n = 1'b1; + flash_rst_n = 1'b1; + cpu_ready = 1'b0; + data_dir = 1'b0; + flash_addr = cpu_addr; + data_out_reg = {DATA_WIDTH{1'b0}}; + + case (state) + IDLE: begin + cpu_ready = 1'b1; + flash_ce_n = 1'b0; + + if (cpu_read) begin + next_state = READ; + end else if (cpu_write) begin + next_state = WRITE_CMD; + end else if (cpu_erase_sector) begin + next_state = ERASE_CMD; + end + end + + READ: begin + flash_ce_n = 1'b0; + flash_oe_n = 1'b0; + flash_we_n = 1'b1; + cpu_data_out = flash_data; + cpu_ready = 1'b1; + next_state = IDLE; + end + + WRITE_CMD: begin + flash_ce_n = 1'b0; + flash_we_n = 1'b0; + data_dir = 1'b1; + data_out_reg = CMD_WRITE; + next_state = WRITE_DATA; + end + + WRITE_DATA: begin + flash_ce_n = 1'b0; + flash_we_n = 1'b0; + data_dir = 1'b1; + data_out_reg = cpu_data_in; + next_state = WAIT_READY; + end + + ERASE_CMD: begin + flash_ce_n = 1'b0; + flash_we_n = 1'b0; + data_dir = 1'b1; + data_out_reg = CMD_ERASE; + next_state = WAIT_READY; + end + + WAIT_READY: begin + flash_ce_n = 1'b0; + if (flash_ready) begin + cpu_ready = 1'b1; + next_state = IDLE; + end + end + + default: begin + next_state = IDLE; + end + endcase + end + +endmodule From f024c9db55fad91c5c7fce6ac76c4d6c0db9dfda Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 03:10:12 +0000 Subject: [PATCH 3/4] Fix NAND flash controller: correct high-impedance syntax and status register handling Co-authored-by: ewdlop <25368970+ewdlop@users.noreply.github.com> --- Misc/Flash-Memory/nand_flash_controller.v | 26 +++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Misc/Flash-Memory/nand_flash_controller.v b/Misc/Flash-Memory/nand_flash_controller.v index fd19d6e..9350db9 100644 --- a/Misc/Flash-Memory/nand_flash_controller.v +++ b/Misc/Flash-Memory/nand_flash_controller.v @@ -61,7 +61,8 @@ module nand_flash_controller #( localparam ERASE_ADDR = 4'd11; localparam ERASE_CMD2 = 4'd12; localparam WAIT_READY = 4'd13; - localparam READ_STATUS_STATE = 4'd14; + localparam STATUS_CMD = 4'd14; + localparam STATUS_READ = 4'd15; reg [3:0] state, next_state; reg [7:0] io_out; @@ -71,7 +72,7 @@ module nand_flash_controller #( reg [7:0] status_reg; // Bidirectional I/O control - assign flash_io = io_dir ? io_out : 8'hzz; + assign flash_io = io_dir ? io_out : 8'hz; // Page buffer (simplified - in real implementation would be larger) reg [DATA_WIDTH-1:0] page_buffer [0:PAGE_SIZE-1]; @@ -82,6 +83,7 @@ module nand_flash_controller #( state <= IDLE; addr_cycle <= 4'd0; byte_counter <= 16'd0; + status_reg <= 8'h00; end else begin state <= next_state; @@ -98,6 +100,11 @@ module nand_flash_controller #( end else begin byte_counter <= 16'd0; end + + // Capture status register when reading + if (state == STATUS_READ) begin + status_reg <= flash_io; + end end end @@ -278,26 +285,27 @@ module nand_flash_controller #( WAIT_READY: begin flash_ce_n = 1'b0; if (flash_rb_n == 1'b1) begin - next_state = READ_STATUS_STATE; + next_state = STATUS_CMD; end end - READ_STATUS_STATE: begin + STATUS_CMD: begin flash_ce_n = 1'b0; flash_cle = 1'b1; flash_we_n = 1'b0; io_dir = 1'b1; io_out = CMD_READ_STATUS; - - // Read status register + next_state = STATUS_READ; + end + + STATUS_READ: begin + flash_ce_n = 1'b0; flash_re_n = 1'b0; - status_reg = flash_io; - + // Status register is captured in sequential logic // Check for errors (bit 0 indicates pass/fail) if (status_reg[0] == 1'b1) begin host_error = 1'b1; end - next_state = IDLE; end From 28aae4325dc7d8abd13a92caca6702a17adaf5d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 03:13:39 +0000 Subject: [PATCH 4/4] Improve NAND flash controller: expand state register and add proper timing for status read Co-authored-by: ewdlop <25368970+ewdlop@users.noreply.github.com> --- Misc/Flash-Memory/nand_flash_controller.v | 49 +++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/Misc/Flash-Memory/nand_flash_controller.v b/Misc/Flash-Memory/nand_flash_controller.v index 9350db9..e68f68e 100644 --- a/Misc/Flash-Memory/nand_flash_controller.v +++ b/Misc/Flash-Memory/nand_flash_controller.v @@ -47,24 +47,25 @@ module nand_flash_controller #( localparam CMD_READ_STATUS = 8'h70; // State machine states - localparam IDLE = 4'd0; - localparam READ_CMD1 = 4'd1; - localparam READ_ADDR = 4'd2; - localparam READ_CMD2 = 4'd3; - localparam READ_WAIT = 4'd4; - localparam READ_DATA = 4'd5; - localparam WRITE_CMD1 = 4'd6; - localparam WRITE_ADDR = 4'd7; - localparam WRITE_DATA = 4'd8; - localparam WRITE_CMD2 = 4'd9; - localparam ERASE_CMD1 = 4'd10; - localparam ERASE_ADDR = 4'd11; - localparam ERASE_CMD2 = 4'd12; - localparam WAIT_READY = 4'd13; - localparam STATUS_CMD = 4'd14; - localparam STATUS_READ = 4'd15; + localparam IDLE = 5'd0; + localparam READ_CMD1 = 5'd1; + localparam READ_ADDR = 5'd2; + localparam READ_CMD2 = 5'd3; + localparam READ_WAIT = 5'd4; + localparam READ_DATA = 5'd5; + localparam WRITE_CMD1 = 5'd6; + localparam WRITE_ADDR = 5'd7; + localparam WRITE_DATA = 5'd8; + localparam WRITE_CMD2 = 5'd9; + localparam ERASE_CMD1 = 5'd10; + localparam ERASE_ADDR = 5'd11; + localparam ERASE_CMD2 = 5'd12; + localparam WAIT_READY = 5'd13; + localparam STATUS_CMD = 5'd14; + localparam STATUS_READ_WAIT = 5'd15; + localparam STATUS_READ = 5'd16; - reg [3:0] state, next_state; + reg [4:0] state, next_state; reg [7:0] io_out; reg io_dir; // 0 = input from flash, 1 = output to flash reg [3:0] addr_cycle; @@ -101,8 +102,8 @@ module nand_flash_controller #( byte_counter <= 16'd0; end - // Capture status register when reading - if (state == STATUS_READ) begin + // Capture status register when reading (after flash_io stabilizes) + if (state == STATUS_READ_WAIT) begin status_reg <= flash_io; end end @@ -295,13 +296,19 @@ module nand_flash_controller #( flash_we_n = 1'b0; io_dir = 1'b1; io_out = CMD_READ_STATUS; + next_state = STATUS_READ_WAIT; + end + + STATUS_READ_WAIT: begin + flash_ce_n = 1'b0; + flash_re_n = 1'b0; + // Wait one cycle for flash_io to stabilize next_state = STATUS_READ; end STATUS_READ: begin flash_ce_n = 1'b0; - flash_re_n = 1'b0; - // Status register is captured in sequential logic + // Status register is captured in sequential logic on entry to this state // Check for errors (bit 0 indicates pass/fail) if (status_reg[0] == 1'b1) begin host_error = 1'b1;