SummerCart64/fw/rtl/n64/n64_bootloader.sv
2022-02-02 19:07:43 +01:00

95 lines
2.5 KiB
Systemverilog

module n64_bootloader (
if_system.sys sys,
if_n64_bus bus,
if_config.flash cfg,
if_flash.flash flash
);
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
typedef enum bit [0:0] {
T_N64,
T_CPU
} e_source_request;
e_state state;
e_source_request source_request;
logic request;
logic ack;
logic write;
logic [31:0] address;
logic [31:0] wdata;
logic [31:0] rdata;
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
state <= S_IDLE;
request <= 1'b0;
end else begin
case (state)
S_IDLE: begin
if (bus.request || flash.request) begin
state <= S_WAIT;
request <= 1'b1;
if (bus.request) begin
write <= 1'b0;
address <= bus.address;
wdata <= bus.wdata;
source_request <= T_N64;
end else if (flash.request) begin
write <= flash.write;
address <= flash.address;
wdata <= flash.wdata;
source_request <= T_CPU;
end
end
end
S_WAIT: begin
if (ack) begin
state <= S_IDLE;
request <= 1'b0;
end
end
endcase
end
end
always_comb begin
bus.ack = source_request == T_N64 && ack;
bus.rdata = 16'd0;
if (bus.ack && bus.address < 32'h00010000) begin
if (bus.address[1]) bus.rdata = {rdata[23:16], rdata[31:24]};
else bus.rdata = {rdata[7:0], rdata[15:8]};
end
flash.ack = source_request == T_CPU && ack;
flash.rdata = 32'd0;
if (flash.ack) begin
flash.rdata = rdata;
end
end
vendor_flash vendor_flash_inst (
.clk(sys.clk),
.reset(sys.reset),
.erase_start(cfg.flash_erase_start),
.erase_busy(cfg.flash_erase_busy),
.wp_enable(cfg.flash_wp_enable),
.wp_disable(cfg.flash_wp_disable),
.request(request),
.ack(ack),
.write(write),
.address(address),
.wdata(wdata),
.rdata(rdata)
);
endmodule