---
# System prepended metadata

title: Caravel soc - storage
tags: [caravel]

---

# Caravel soc - storage
###### tags: `caravel`
https://github.com/bol-edu/caravel-soc
## SRAM
![](https://i.imgur.com/gBi4hOh.png)

```verilog=
// Housekeeping
`ifdef USE_SRAM_RO_INTERFACE
    output sram_ro_clk,
    output sram_ro_csb,
    output [7:0] sram_ro_addr,
    input [31:0] sram_ro_data,
`endif
```
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/housekeeping.v#L218

The 4 signals are not wired.
## RAM
### RAM128/256
```verilog=
module RAM128 #( parameter COLS=1)
    localparam A_WIDTH = 7+$clog2(COLS);
    input   wire    [(A_WIDTH - 1): 0]   A0;
    reg [31:0] RAM[(256*COLS)-1 : 0];

    always @(posedge CLK)
        if(EN0) begin
            Do0 <= RAM[A0];
            if(WE0[0]) RAM[A0][ 7: 0] <= Di0[7:0];
            if(WE0[1]) RAM[A0][15:8] <= Di0[15:8];
            if(WE0[2]) RAM[A0][23:16] <= Di0[23:16];
            if(WE0[3]) RAM[A0][31:24] <= Di0[31:24];
        end
        else
            Do0 <= 32'b0;

endmodule
module RAM256 #( parameter COLS=1)
    localparam A_WIDTH = 8+$clog2(COLS);
    input   wire    [(A_WIDTH - 1): 0]   A0;
    reg [31:0] RAM[(256*COLS)-1 : 0];

    always @(posedge CLK)
        if(EN0) begin
            Do0 <= RAM[A0];
            if(WE0[0]) RAM[A0][ 7: 0] <= Di0[7:0];
            if(WE0[1]) RAM[A0][15:8] <= Di0[15:8];
            if(WE0[2]) RAM[A0][23:16] <= Di0[23:16];
            if(WE0[3]) RAM[A0][31:24] <= Di0[31:24];
        end
        else
            Do0 <= 32'b0;

endmodule
```
https://github.com/bol-edu/caravel-soc/blob/main/vip/RAM128.v
https://github.com/bol-edu/caravel-soc/blob/main/vip/RAM256.v

The only difference is address width.

### Usage
```verilog=
RAM256 RAM256(
	.A0(dff_bus_adr[7:0]),
	.CLK(sys_clk),
	.Di0(dff_di),
	.EN0(dff_en),
	.WE0(dff_we),
	.Do0(dff_do)
);

RAM128 RAM128(
	.A0(dff2_bus_adr[6:0]),
	.CLK(sys_clk),
	.Di0(dff2_di),
	.EN0(dff2_en),
	.WE0(dff2_we),
	.Do0(dff2_do)
);
```
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L8374
```
MEMORY {
	vexriscv_debug : ORIGIN = 0xf00f0000, LENGTH = 0x00000100
	dff : ORIGIN = 0x00000000, LENGTH = 0x00000400
	dff2 : ORIGIN = 0x00000400, LENGTH = 0x00000200
	flash : ORIGIN = 0x10000000, LENGTH = 0x01000000
	mprj : ORIGIN = 0x30000000, LENGTH = 0x00100000
	hk : ORIGIN = 0x26000000, LENGTH = 0x00100000
	csr : ORIGIN = 0xf0000000, LENGTH = 0x00010000
}

// dff => RAM256
// dff2 => RAM128
```
https://github.com/bol-edu/caravel-soc/blob/main/firmware/sections.lds#L11


### Slave select
```verilog=
wire [29:0] shared_adr; // Shift left 2 bit from 32 bits address
always @(*) begin
	slave_sel = 7'd0;
	slave_sel[0] = (shared_adr[29:6] == 24'd15732480);
	slave_sel[1] = (shared_adr[29:8] == 1'd0);
	slave_sel[2] = (shared_adr[29:7] == 2'd2);
	slave_sel[3] = (shared_adr[29:22] == 5'd16);
	slave_sel[4] = (shared_adr[29:26] == 2'd3);
	slave_sel[5] = (shared_adr[29:20] == 8'd152);
	// 641440 << 2 = 0x3c000
	// 0x3c000 << 14 = 0xf0000000
	slave_sel[6] = (shared_adr[29:14] == 16'd61440);
end

assign mgmtsoc_vexriscv_debug_bus_cyc = (shared_cyc & slave_sel[0]);
assign dff_bus_cyc = (shared_cyc & slave_sel[1]);
assign dff2_bus_cyc = (shared_cyc & slave_sel[2]);
assign mgmtsoc_litespimmap_bus_cyc = (shared_cyc & slave_sel[3]);
assign mprj_cyc = (shared_cyc & slave_sel[4]);
assign hk_cyc = (shared_cyc & slave_sel[5]);
assign mgmtsoc_wishbone_cyc = (shared_cyc & slave_sel[6]);
```
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L4827
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L4886

### Test
```cpp=
int a, b;
int main (int argc, char **argv)
{
    a = 0x1234;
    b = (int)&a;
    int c = 0x5566;
    int d = (int)&c;
    return 0;
}
```
```
MEMORY {
	dff : ORIGIN = 0x00000000, LENGTH = 0x00000400
	dff2 : ORIGIN = 0x00000400, LENGTH = 0x00000200
}

SECTIONS
{
	.bss :
	{
	} > dff
}

PROVIDE(_fstack = ORIGIN(dff2) + LENGTH(dff2));
```
https://github.com/bol-edu/caravel-soc/blob/main/firmware/sections.lds#L58

Expect global variables(`a, b`) locate in `dff` region and local variables(`c`,`d`) locate near top of stack(`dff2`).
![](https://i.imgur.com/uoirOvx.png)
![](https://i.imgur.com/vm5wXB3.png)



|  | Firmware | Hardware |
| -------| -------- | -------- |
| &a     | 0x0004   | 0x01(ram256)|
| &b     | 0x0008   | 0x02(ram256)|
| &c     | 0x05e8   | 0x7a(ram128)|
| &d     | 0x05ec   | 0x7b(ram128)|

0x7a = (0x5e8 - 0x400) / 0x04;

## Flash
![](https://i.imgur.com/lpbwcVP.png)

### Simulator
* [PicoSoC](https://github.com/bol-edu/caravel-soc/blob/main/vip/spiflash.v#L5) - A simple example SoC using PicoRV32
    * Cypress S25FL064L
* 128 Mbits
* No write protect or reset pin

#### Supported Commands
| Function | Hex |
| -------| --------|
| Release from Deep Power down | AB |
| Deep Power-down | B9 |
| Mode Bit Reset | FF |
| Read | 03 |
| Dual I/O Read | BB |
| Quad I/O Read | EB |
| DDR Quad I/O Read | ED |

The only command we used is `Read`.

[The SPI protocol does not specify whether the most-significant bit (MSb) or least-significant bit (LSb) is transmitted or received first during an SPI transfer.](http://quanser-update.azurewebsites.net/quarc/documentation/spi_protocol.html#:~:text=The%20SPI%20protocol%20does%20not,order%20of%20the%20SPI%20transfer.)

![](https://i.imgur.com/9BF5LxG.png)
![](https://i.imgur.com/cKkp5Sc.png)

#### Dummy cycle
* Only for daul/quad read, single read and write do not need dummy cycle
* Can be configured in 
    * flash(CR3NV/CR3V register)
    * [flash simulator](https://github.com/bol-edu/caravel-soc/blob/main/vip/spiflash.v#L51)
    * flash controller
        * https://github.com/bol-edu/caravel-soc/blob/main/firmware/csr.h#L102
        * https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L4997
        * [Document is wrong](https://caravel-harness.readthedocs.io/en/latest/qspi-flash.html#reg-spictrl-access-mode-values)

#### Implementation
```verilog=
always @(posedge clk) begin
    if (!csb) begin
        case (mode)
            mode_spi: begin
                buffer = {buffer, io0};
                bitcount = bitcount + 1;
                if (bitcount == 8) begin
                    bitcount = 0;
                    bytecount = bytecount + 1;
                    spi_action;
                end
            end
        endcase
    end
end

if (powered_up && spi_cmd == 'h 03) begin
    if (bytecount == 2)
        spi_addr[23:16] = buffer;

    if (bytecount == 3)
        spi_addr[15:8] = buffer;

    if (bytecount == 4)
        spi_addr[7:0] = buffer;

    if (bytecount >= 4) begin
        buffer = memory[spi_addr];
        spi_addr = spi_addr + 1;
    end
end
```
https://github.com/bol-edu/caravel-soc/blob/main/vip/spiflash.v#L405
https://github.com/bol-edu/caravel-soc/blob/main/vip/spiflash.v#L121

### Controller
#### Data & length
```verilog=
mgmtsoc_litespimmap_source_payload_data = 32'd0;
case (litespi_state)
    1'd1: begin
        mgmtsoc_litespimmap_source_payload_data = 2'd3; // Read command
    end
    2'd3: begin
        mgmtsoc_litespimmap_source_payload_data = {mgmtsoc_litespimmap_bus_adr, mgmtsoc_litespimmap}; // shared_addr << 2
    end
    3'd4: begin
    end
    3'd5: begin
        mgmtsoc_litespimmap_source_payload_data = mgmtsoc_litespimmap_dummy;
    end
    default: begin
    end
endcase
// ...
mgmtsoc_litespimmap_source_payload_len = 6'd0;
case (litespi_state)
    1'd1: begin
        mgmtsoc_litespimmap_source_payload_len = 4'd8; // Cmd length
    end
    2'd3: begin
        mgmtsoc_litespimmap_source_payload_len = 5'd24; // Address length
    end
    3'd5: begin
        mgmtsoc_litespimmap_source_payload_len = mgmtsoc_litespimmap_spi_dummy_bits;
    end
    3'd7: begin
        mgmtsoc_litespimmap_source_payload_len = 6'd32; // Data length
    end
    default: begin
    end
endcase
```
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L2608

#### Data source selected
Just like Wishbone, spi out to padframe has different source.
```=verilog
assign litespi_request = {mgmtsoc_port_master_request, mgmtsoc_port_mmap_request};
// ...
case (litespi_grant)
    1'd0: begin
        if ((~litespi_request[0])) begin
            if (litespi_request[1]) begin
                litespi_grant <= 1'd1;
            end
        end
    end
    1'd1: begin
        if ((~litespi_request[1])) begin
            if (litespi_request[0]) begin
                litespi_grant <= 1'd0;
            end
        end
    end
endcase
// ...
assign litespi_tx_mux_sel = litespi_grant;
// ...
always @(*) begin
	litespi_tx_mux_source_payload_data = 32'd0;
	case (litespi_tx_mux_sel)
		1'd0: begin
			litespi_tx_mux_source_payload_data = litespi_tx_mux_endpoint0_sink_payload_data;
		end
		1'd1: begin
			litespi_tx_mux_source_payload_data = litespi_tx_mux_endpoint1_sink_payload_data;
		end
	endcase
end
```
#### Send data bit by bit
```=verilog
if (mgmtsoc_litespisdrphycore_sr_out_load) begin
    mgmtsoc_litespisdrphycore_sr_out <= (mgmtsoc_litespisdrphycore_sink_payload_data <<< (6'd32 - mgmtsoc_litespisdrphycore_sink_payload_len));
end
if (mgmtsoc_litespisdrphycore_sr_out_shift) begin
    case (mgmtsoc_litespisdrphycore_sink_payload_width)
        1'd1: begin
            mgmtsoc_litespisdrphycore_sr_out <= {mgmtsoc_litespisdrphycore_sr_out, mgmtsoc_litespisdrphycore0};
        end
        2'd2: begin
            mgmtsoc_litespisdrphycore_sr_out <= {mgmtsoc_litespisdrphycore_sr_out, mgmtsoc_litespisdrphycore1};
        end
        3'd4: begin
            mgmtsoc_litespisdrphycore_sr_out <= {mgmtsoc_litespisdrphycore_sr_out, mgmtsoc_litespisdrphycore2};
        end
        4'd8: begin
            mgmtsoc_litespisdrphycore_sr_out <= {mgmtsoc_litespisdrphycore_sr_out, mgmtsoc_litespisdrphycore3};
        end
    endcase
end
```
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L2179
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L2249
https://github.com/bol-edu/caravel-soc/blob/main/rtl/soc/mgmt_core.v#L6805
#### Check state machine
No dummy state
![](https://i.imgur.com/JYQYIhm.png)
Just keep read data state
![](https://i.imgur.com/8Et2nwu.png)
#### Check timing to fetch next bit
Clock for flash is not wired directly
![](https://i.imgur.com/sjQARhI.png)


## Reference
https://github.com/YosysHQ/picorv32/blob/master/picosoc/spiflash.v
http://www.cypress.com/file/316661/download