SummerCart64/fw/rtl/cpu/cpu_dd.sv

142 lines
4.7 KiB
Systemverilog

module cpu_dd (
if_system.sys sys,
if_cpu_bus bus,
if_dd.cpu dd
);
const bit [8:0] M_SECTOR_BUFFER = 9'h100;
logic bm_ack;
logic [31:0] seek_timer;
typedef enum bit [2:0] {
R_SCR,
R_CMD_DATA,
R_HEAD_TRACK,
R_SECTOR_INFO,
R_DRIVE_ID,
R_SEEK_TIMER
} e_reg_id;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
bus.ack <= 1'b1;
end
end
always_comb begin
bus.rdata = 32'd0;
if (bus.ack) begin
if (bus.address[8] == M_SECTOR_BUFFER[8]) begin
bus.rdata = {
dd.sector_rdata[7:0],
dd.sector_rdata[15:8],
dd.sector_rdata[23:16],
dd.sector_rdata[31:24]
};
end else begin
case (bus.address[5:2])
R_SCR: bus.rdata = {
14'd0,
bm_ack,
dd.bm_micro_error,
dd.bm_transfer_c2,
dd.bm_transfer_data,
dd.bm_transfer_blocks,
dd.bm_transfer_mode,
1'b0,
dd.bm_stop_pending,
1'b0,
dd.bm_start_pending,
dd.disk_changed,
dd.disk_inserted,
1'b0,
dd.bm_pending,
1'b0,
dd.cmd_pending,
1'b0,
dd.hard_reset
};
R_CMD_DATA: bus.rdata = {8'd0, dd.cmd, dd.data};
R_HEAD_TRACK: bus.rdata = {18'd0, dd.index_lock, dd.head_track};
R_SECTOR_INFO: bus.rdata = {
dd.sectors_in_block,
dd.sector_size_full,
dd.sector_size,
dd.sector_num
};
R_DRIVE_ID: bus.rdata = {dd.drive_id};
R_SEEK_TIMER: bus.rdata = seek_timer;
default: bus.rdata = 32'd0;
endcase
end
end
end
always_comb begin
dd.sector_address = bus.address[7:2];
dd.sector_address_valid = bus.request && bus.address[8] == M_SECTOR_BUFFER[8];
dd.sector_write = (&bus.wmask) && dd.sector_address_valid;
dd.sector_wdata = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
end
always_ff @(posedge sys.clk) begin
dd.hard_reset_clear <= 1'b0;
dd.cmd_ready <= 1'b0;
dd.bm_start_clear <= 1'b0;
dd.bm_stop_clear <= 1'b0;
dd.bm_clear <= 1'b0;
dd.bm_ready <= 1'b0;
if (dd.bm_interrupt_ack) begin
bm_ack <= 1'b1;
end
if (!(&seek_timer)) begin
seek_timer <= seek_timer + 1'd1;
end
if (sys.reset) begin
bm_ack <= 1'b0;
end else begin
if (bus.request && (!bus.address[8])) begin
case (bus.address[4:2])
R_SCR: if (&bus.wmask) begin
if (bus.wdata[20]) begin
seek_timer <= 32'd0;
end
dd.bm_clear <= bus.wdata[19];
if (bus.wdata[18]) begin
bm_ack <= 1'b0;
end
dd.bm_micro_error <= bus.wdata[16];
dd.bm_transfer_c2 <= bus.wdata[15];
dd.bm_transfer_data <= bus.wdata[14];
dd.bm_stop_clear <= bus.wdata[11];
dd.bm_start_clear <= bus.wdata[9];
dd.disk_changed <= bus.wdata[7];
dd.disk_inserted <= bus.wdata[6];
dd.bm_ready <= bus.wdata[5];
dd.cmd_ready <= bus.wdata[3];
dd.hard_reset_clear <= bus.wdata[1];
end
R_CMD_DATA: if (&bus.wmask[1:0]) begin
dd.cmd_data <= bus.wdata[15:0];
end
R_HEAD_TRACK: if (&bus.wmask[1:0]) begin
{dd.index_lock, dd.head_track} <= bus.wdata[13:0];
end
R_DRIVE_ID: if (&bus.wmask[1:0]) begin
dd.drive_id <= bus.wdata[15:0];
end
endcase
end
end
end
endmodule