mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-27 21:41:55 +01:00
ff69030643
* isv support + usb/dd improvements
* make room for saves
* update offset
* fixed debug address
* idk
* exception
* ironed out all broken stuff
* cleanup
* return epc fix
* better
* more cleanup
* even more cleanup
* mooore cleanup
* fixed printf
* no assert
* improved docker build, pyft232 instead of pyserial
* fixed displaying long message strings
description test
* just straight cleanup
* smallest cleanup
* PAL
* cpu buffer
* n64 bootloader done
* super slow usb storage reading implemented
* reduced buffer size
* usb gets fast
* little cleanup
* double buffered reads
* removed separate event id
* ISV in hardware finally
* small exception changes
* mac testing
* py spacing
* fsd write, rtc, isv and reset fixes
* fixxx
* good stopping point
* usb fixed?
* pretend we have 128 MB sdram
* backup
* chmod
* test
* test done
* more tests
* user rm
* help
* final fix
* updated component values
* nice asset names
* cic 64dd support
* ddipl enable separation
* pre DMA rewrite, created dedicated buffer memory space, simplified code
* dma rewrite, needs testing
* moved xml
* dd basics
* timing
* 64dd working yet again, isv brought back, dma fixes, usb path rewrite, pc code rewrite
* added usb read functionality, general cleanup
* changed mem addressing
* added fpga flash update access
* added mcu update
* chmod
* little cleanup
* update format and stuff
* fixes
* uninitialized fix
* small fixes
* update fixes
* update stuff done
* fpga update tested
* build time fix
* boot fix
* test timing
* readme test
* test 2
* reports
* testseet
* final
* build test
* forgot
* button and naming
* General cleanup
And multiline commit message test
* Exception screen UI touch ups
* display separation and tests beginning
* pc software update
* pc software done
* timing test
* delete launch.json
* sw fixes
* fixed button hole diameter in shell
* small cleanup, rpi testing
* shell fillet fix, pc rtc printing
* added cfg lock mechanism
* moved lock to cfg address space
* extended ROM and ISV fixes
* preliminary sd card support
* little sd card cleanup
* sd menu fixes
* 5 second limit
* reduced shell thickness
* basic led act blinking
* faster sd menu loading
* inst cache invalidate
* sd card writing is working
* SD card CSD and CID registers
* wait for previous command
* led error codes
* fixed cfg_translate_address use
* 64dd from sd card working
* 64dd speedup and button handling
* delayed address latching cycle - might break other builds, needs testing
* bootloader improvements
* small fixes
* return previous cfg when setting new
* cache stuff
* unfloader debug protocol support
* UNFLoader style debug command line support
* requirements.txt
* shell groove fillet
* reset state inside controller
* fixed fast PI read, added PI R/W fifo debug info
* PI access prioritize
* SD clock stop when RX FIFO is more than half full
* flash erase method change
* CFG error handling, TLOZ MM debug ISV support
* CIC5167 support
* general fixes
* USB unplugged cable handling
* turn off led when changing between error/act modes
* rtc 2 bit clock stop support
* line endings
* Revert "line endings"
This reverts commit d0ddfe5ec7
.
* PI address debug
* readme test
* diagram update
* diagram background
* diagram background
* diagram background
* updated readme
493 lines
16 KiB
Systemverilog
493 lines
16 KiB
Systemverilog
interface flash_scb ();
|
|
|
|
logic erase_pending;
|
|
logic erase_done;
|
|
logic [7:0] erase_block;
|
|
|
|
modport controller (
|
|
output erase_pending,
|
|
input erase_done,
|
|
output erase_block
|
|
);
|
|
|
|
modport flash (
|
|
input erase_pending,
|
|
output erase_done,
|
|
input erase_block
|
|
);
|
|
|
|
endinterface
|
|
|
|
|
|
module flash_qspi (
|
|
input clk,
|
|
input reset,
|
|
|
|
input start,
|
|
input finish,
|
|
output logic busy,
|
|
output logic valid,
|
|
input output_enable,
|
|
input quad_enable,
|
|
output logic [7:0] rdata,
|
|
input [7:0] wdata,
|
|
|
|
output logic flash_clk,
|
|
output logic flash_cs,
|
|
inout [3:0] flash_dq
|
|
);
|
|
|
|
logic flash_dq_oe_s;
|
|
logic flash_dq_oe_q;
|
|
logic [3:0] flash_dq_out;
|
|
|
|
assign flash_dq[0] = flash_dq_oe_s ? flash_dq_out[0] : 1'bZ;
|
|
assign flash_dq[3:1] = flash_dq_oe_q ? flash_dq_out[3:1] : 3'bZZZ;
|
|
|
|
logic ff_clk;
|
|
logic ff_cs;
|
|
logic ff_dq_oe_s;
|
|
logic ff_dq_oe_q;
|
|
logic [3:0] ff_dq_out;
|
|
logic [3:0] ff_dq_in;
|
|
|
|
always_ff @(posedge clk) begin
|
|
flash_clk <= ff_clk;
|
|
flash_cs <= ff_cs;
|
|
flash_dq_oe_s <= ff_dq_oe_s;
|
|
flash_dq_oe_q <= ff_dq_oe_q;
|
|
flash_dq_out <= ff_dq_out;
|
|
ff_dq_in <= flash_dq;
|
|
end
|
|
|
|
logic running;
|
|
logic exit;
|
|
logic valid_enable;
|
|
logic quad_mode;
|
|
logic [2:0] counter;
|
|
logic [7:0] output_shift;
|
|
logic [2:0] sample_s;
|
|
logic [2:0] sample_q;
|
|
logic [2:0] valid_ff;
|
|
|
|
assign ff_dq_out = quad_mode ? output_shift[7:4] : {3'bXXX, output_shift[7]};
|
|
|
|
always_ff @(posedge clk) begin
|
|
sample_s <= {sample_s[1:0], 1'b0};
|
|
sample_q <= {sample_q[1:0], 1'b0};
|
|
valid_ff <= {valid_ff[1:0], 1'b0};
|
|
if (reset) begin
|
|
ff_clk <= 1'b0;
|
|
ff_cs <= 1'b1;
|
|
ff_dq_oe_s <= 1'b0;
|
|
ff_dq_oe_q <= 1'b0;
|
|
busy <= 1'b0;
|
|
running <= 1'b0;
|
|
end else begin
|
|
if (running) begin
|
|
ff_clk <= ~ff_clk;
|
|
if (!ff_clk) begin
|
|
if (counter == 3'd0) begin
|
|
busy <= 1'b0;
|
|
valid_ff[0] <= valid_enable;
|
|
end
|
|
if (!quad_mode) begin
|
|
sample_s[0] <= 1'b1;
|
|
end else begin
|
|
sample_q[0] <= 1'b1;
|
|
end
|
|
end else begin
|
|
counter <= counter - 1'd1;
|
|
if (counter == 3'd0) begin
|
|
running <= 1'b0;
|
|
end
|
|
if (!quad_mode) begin
|
|
output_shift <= {output_shift[6:0], 1'bX};
|
|
end else begin
|
|
output_shift <= {output_shift[3:0], 4'bXXXX};
|
|
end
|
|
end
|
|
end
|
|
|
|
if (exit) begin
|
|
ff_cs <= 1'b1;
|
|
counter <= counter - 1'd1;
|
|
if (counter == 3'd0) begin
|
|
busy <= 1'b0;
|
|
exit <= 1'b0;
|
|
end
|
|
end
|
|
|
|
if (!busy) begin
|
|
if (start) begin
|
|
ff_clk <= 1'b0;
|
|
ff_cs <= 1'b0;
|
|
ff_dq_oe_s <= !quad_enable || (quad_enable && output_enable);
|
|
ff_dq_oe_q <= quad_enable && output_enable;
|
|
busy <= 1'b1;
|
|
running <= 1'b1;
|
|
valid_enable <= !output_enable;
|
|
quad_mode <= quad_enable;
|
|
counter <= quad_enable ? 3'd1 : 3'd7;
|
|
output_shift <= wdata;
|
|
end else if (finish) begin
|
|
busy <= 1'b1;
|
|
exit <= 1'b1;
|
|
counter <= wdata[2:0];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
always_ff @(posedge clk) begin
|
|
valid <= 1'b0;
|
|
if (sample_s[2]) begin
|
|
rdata <= {rdata[6:0], ff_dq_in[1]};
|
|
end
|
|
if (sample_q[2]) begin
|
|
rdata <= {rdata[3:0], ff_dq_in};
|
|
end
|
|
if (valid_ff[2]) begin
|
|
valid <= 1'b1;
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
module memory_flash (
|
|
input clk,
|
|
input reset,
|
|
|
|
flash_scb.flash flash_scb,
|
|
|
|
mem_bus.memory mem_bus,
|
|
|
|
output flash_clk,
|
|
output flash_cs,
|
|
inout [3:0] flash_dq
|
|
);
|
|
|
|
logic start;
|
|
logic finish;
|
|
logic busy;
|
|
logic valid;
|
|
logic output_enable;
|
|
logic quad_enable;
|
|
logic [7:0] rdata;
|
|
logic [7:0] wdata;
|
|
|
|
flash_qspi flash_qspi_inst (
|
|
.clk(clk),
|
|
.reset(reset),
|
|
|
|
.start(start),
|
|
.finish(finish),
|
|
.busy(busy),
|
|
.valid(valid),
|
|
.output_enable(output_enable),
|
|
.quad_enable(quad_enable),
|
|
.rdata(rdata),
|
|
.wdata(wdata),
|
|
|
|
.flash_clk(flash_clk),
|
|
.flash_cs(flash_cs),
|
|
.flash_dq(flash_dq)
|
|
);
|
|
|
|
typedef enum bit [7:0] {
|
|
FLASH_CMD_PAGE_PROGRAM = 8'h02,
|
|
FLASH_CMD_READ_STATUS_1 = 8'h05,
|
|
FLASH_CMD_WRITE_ENABLE = 8'h06,
|
|
FLASH_CMD_BLOCK_ERASE_64KB = 8'hD8,
|
|
FLASH_CMD_FAST_READ_QUAD_IO = 8'hEB
|
|
} e_flash_cmd;
|
|
|
|
typedef enum {
|
|
FLASH_STATUS_1_BUSY = 0
|
|
} e_flash_status_1;
|
|
|
|
typedef enum bit [3:0] {
|
|
STATE_IDLE,
|
|
STATE_WRITE_ENABLE,
|
|
STATE_ERASE,
|
|
STATE_PROGRAM_START,
|
|
STATE_PROGRAM,
|
|
STATE_PROGRAM_END,
|
|
STATE_WAIT,
|
|
STATE_READ_START,
|
|
STATE_READ,
|
|
STATE_READ_END
|
|
} e_state;
|
|
|
|
e_state state;
|
|
logic [2:0] counter;
|
|
logic valid_counter;
|
|
logic [23:0] current_address;
|
|
|
|
always_ff @(posedge clk) begin
|
|
start <= 1'b0;
|
|
finish <= 1'b0;
|
|
flash_scb.erase_done <= 1'b0;
|
|
mem_bus.ack <= 1'b0;
|
|
|
|
if (reset) begin
|
|
state <= STATE_IDLE;
|
|
end else begin
|
|
if (!busy && (start || finish)) begin
|
|
counter <= counter + 1'd1;
|
|
end
|
|
|
|
case (state)
|
|
STATE_IDLE: begin
|
|
output_enable <= 1'b1;
|
|
quad_enable <= 1'b0;
|
|
counter <= 3'd0;
|
|
if (flash_scb.erase_pending) begin
|
|
state <= STATE_WRITE_ENABLE;
|
|
end else if (mem_bus.request) begin
|
|
current_address <= {mem_bus.address[23:1], 1'b0};
|
|
if (mem_bus.write) begin
|
|
state <= STATE_WRITE_ENABLE;
|
|
end else begin
|
|
state <= STATE_READ_START;
|
|
end
|
|
end
|
|
end
|
|
|
|
STATE_WRITE_ENABLE: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
wdata <= FLASH_CMD_WRITE_ENABLE;
|
|
end
|
|
3'd1: begin
|
|
finish <= 1'b1;
|
|
wdata <= 8'd4;
|
|
if (!busy) begin
|
|
counter <= 3'd0;
|
|
if (flash_scb.erase_pending) begin
|
|
state <= STATE_ERASE;
|
|
end else begin
|
|
state <= STATE_PROGRAM_START;
|
|
end
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
|
|
STATE_ERASE: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
wdata <= FLASH_CMD_BLOCK_ERASE_64KB;
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
wdata <= flash_scb.erase_block;
|
|
end
|
|
3'd2: begin
|
|
start <= 1'b1;
|
|
wdata <= 8'd0;
|
|
end
|
|
3'd3: begin
|
|
start <= 1'b1;
|
|
wdata <= 8'd0;
|
|
end
|
|
3'd4: begin
|
|
finish <= 1'b1;
|
|
wdata <= 8'd4;
|
|
if (!busy) begin
|
|
flash_scb.erase_done <= 1'b1;
|
|
counter <= 3'd0;
|
|
state <= STATE_WAIT;
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
|
|
STATE_PROGRAM_START: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
wdata <= FLASH_CMD_PAGE_PROGRAM;
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.address[23:16];
|
|
end
|
|
3'd2: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.address[15:8];
|
|
end
|
|
3'd3: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.address[7:0];
|
|
if (!busy) begin
|
|
counter <= 3'd0;
|
|
state <= STATE_PROGRAM;
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
|
|
STATE_PROGRAM: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.wdata[15:8];
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.wdata[7:0];
|
|
if (!busy) begin
|
|
mem_bus.ack <= 1'b1;
|
|
current_address <= current_address + 2'd2;
|
|
end
|
|
end
|
|
3'd2: begin
|
|
if (current_address[7:0] == 8'h00) begin
|
|
state <= STATE_PROGRAM_END;
|
|
end else if (flash_scb.erase_pending) begin
|
|
state <= STATE_PROGRAM_END;
|
|
end else if (mem_bus.request && !mem_bus.ack) begin
|
|
if (!mem_bus.write || (mem_bus.address[23:0] != current_address)) begin
|
|
state <= STATE_PROGRAM_END;
|
|
end else begin
|
|
counter <= 3'd0;
|
|
end
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
|
|
STATE_PROGRAM_END: begin
|
|
finish <= 1'b1;
|
|
wdata <= 8'd4;
|
|
if (!busy) begin
|
|
counter <= 3'd0;
|
|
state <= STATE_WAIT;
|
|
end
|
|
end
|
|
|
|
STATE_WAIT: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
output_enable <= 1'b1;
|
|
wdata <= FLASH_CMD_READ_STATUS_1;
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
output_enable <= 1'b0;
|
|
end
|
|
3'd2: begin
|
|
finish <= 1'b1;
|
|
wdata <= 8'd0;
|
|
end
|
|
3'd3: begin
|
|
counter <= counter;
|
|
end
|
|
endcase
|
|
if (valid) begin
|
|
if (rdata[FLASH_STATUS_1_BUSY]) begin
|
|
counter <= 3'd0;
|
|
end else begin
|
|
state <= STATE_IDLE;
|
|
end
|
|
end
|
|
end
|
|
|
|
STATE_READ_START: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
wdata <= FLASH_CMD_FAST_READ_QUAD_IO;
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
quad_enable <= 1'b1;
|
|
wdata <= mem_bus.address[23:16];
|
|
end
|
|
3'd2: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.address[15:8];
|
|
end
|
|
3'd3: begin
|
|
start <= 1'b1;
|
|
wdata <= mem_bus.address[7:0];
|
|
end
|
|
3'd4: begin
|
|
start <= 1'b1;
|
|
wdata <= 8'hFF;
|
|
end
|
|
3'd5: begin
|
|
start <= 1'b1;
|
|
end
|
|
3'd6: begin
|
|
start <= 1'b1;
|
|
if (!busy) begin
|
|
counter <= 3'd0;
|
|
valid_counter <= 1'b0;
|
|
state <= STATE_READ;
|
|
end
|
|
end
|
|
endcase
|
|
end
|
|
|
|
STATE_READ: begin
|
|
case (counter)
|
|
3'd0: begin
|
|
start <= 1'b1;
|
|
output_enable <= 1'b0;
|
|
end
|
|
3'd1: begin
|
|
start <= 1'b1;
|
|
end
|
|
3'd2: begin end
|
|
3'd3: begin
|
|
if (flash_scb.erase_pending) begin
|
|
state <= STATE_READ_END;
|
|
end else if (mem_bus.request && !mem_bus.ack) begin
|
|
if (mem_bus.write || (mem_bus.address[23:0] != current_address)) begin
|
|
state <= STATE_READ_END;
|
|
end else begin
|
|
start <= 1'b1;
|
|
counter <= 3'd0;
|
|
end
|
|
end
|
|
end
|
|
endcase
|
|
if (valid) begin
|
|
valid_counter <= ~valid_counter;
|
|
if (valid_counter) begin
|
|
mem_bus.ack <= 1'b1;
|
|
counter <= counter + 1'd1;
|
|
current_address <= current_address + 2'd2;
|
|
end
|
|
end
|
|
end
|
|
|
|
STATE_READ_END: begin
|
|
finish <= 1'b1;
|
|
wdata <= 8'd0;
|
|
if (!busy) begin
|
|
state <= STATE_IDLE;
|
|
end
|
|
end
|
|
|
|
default: begin
|
|
state <= STATE_IDLE;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (valid) begin
|
|
mem_bus.rdata <= {mem_bus.rdata[7:0], rdata};
|
|
end
|
|
end
|
|
|
|
endmodule
|