Added rf sector buffer
This commit is contained in:
99
rtl/ide.v
Normal file
99
rtl/ide.v
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// ide.v
|
||||
// simple state machine to do proper read & write cycles to ATA IDE device
|
||||
//
|
||||
|
||||
module ide(clk, reset, ata_rd, ata_wr, ata_addr, ata_in, ata_out, ata_done,
|
||||
ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
|
||||
input ata_rd;
|
||||
input ata_wr;
|
||||
input [4:0] ata_addr;
|
||||
input [15:0] ata_in;
|
||||
output [15:0] ata_out;
|
||||
reg [15:0] ata_out;
|
||||
output ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
|
||||
reg [2:0] ata_state;
|
||||
|
||||
parameter [2:0]
|
||||
idle = 3'd0,
|
||||
s0 = 3'd1,
|
||||
s1 = 3'd2,
|
||||
s2 = 3'd3,
|
||||
s3 = 3'd4,
|
||||
s4 = 3'd5;
|
||||
|
||||
wire assert_cs;
|
||||
wire assert_rw;
|
||||
|
||||
reg [2:0] ata_state_next;
|
||||
|
||||
|
||||
// if write, drive ide_bus
|
||||
assign ide_data_bus = (ata_wr && (ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2 ||
|
||||
ata_state == s3)) ? ata_in : 16'bz;
|
||||
|
||||
// assert cs & da during r/w cycle
|
||||
assign assert_cs = (ata_rd || ata_wr) && ata_state != s4;
|
||||
|
||||
assign ide_cs = assert_cs ? ata_addr[4:3] : 2'b11;
|
||||
assign ide_da = assert_cs ? ata_addr[2:0] : 3'b111;
|
||||
|
||||
// assert r/w one cycle sort
|
||||
assign assert_rw = ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2;
|
||||
|
||||
assign ide_dior = (assert_rw && ata_rd) ? 1'b0 : 1'b1;
|
||||
assign ide_diow = (assert_rw && ata_wr) ? 1'b0 : 1'b1;
|
||||
|
||||
// send back done pulse at end
|
||||
assign ata_done = ata_state == s3;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_state <= idle;
|
||||
else
|
||||
ata_state <= ata_state_next;
|
||||
|
||||
always @(clk or ata_state or ata_rd or ata_wr or ata_addr or ide_data_bus)
|
||||
begin
|
||||
case (ata_state)
|
||||
idle:
|
||||
begin
|
||||
if (ata_rd || ata_wr)
|
||||
ata_state_next = s0;
|
||||
else
|
||||
ata_state_next = idle;
|
||||
end
|
||||
|
||||
s0: ata_state_next = s1;
|
||||
s1: ata_state_next = s2;
|
||||
s2: ata_state_next = s3;
|
||||
s3: ata_state_next = s4;
|
||||
s4: ata_state_next = idle;
|
||||
default: ata_state_next = idle;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_out <= 0;
|
||||
else
|
||||
if (ata_state == s2 && ata_rd)
|
||||
ata_out <= ide_data_bus;
|
||||
|
||||
endmodule // ide
|
||||
414
rtl/ide_disk.v
Normal file
414
rtl/ide_disk.v
Normal file
@@ -0,0 +1,414 @@
|
||||
//
|
||||
// ide_disk.v
|
||||
// single block (512 byte/256 work) IDE disk read/write
|
||||
//
|
||||
|
||||
module ide_disk(clk, reset,
|
||||
ide_lba, ide_read_req, ide_write_req,
|
||||
ide_error, ide_done,
|
||||
buffer_addr, buffer_rd, buffer_wr,
|
||||
buffer_in, buffer_out);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input [24:0] ide_lba;
|
||||
input ide_read_req;
|
||||
input ide_write_req;
|
||||
|
||||
output ide_error;
|
||||
output ide_done;
|
||||
|
||||
output [7:0] buffer_addr;
|
||||
output buffer_rd;
|
||||
output buffer_wr;
|
||||
output [11:0] buffer_in;
|
||||
output [11:0] buffer_out;
|
||||
|
||||
parameter [4:0]
|
||||
ready = 5'd0,
|
||||
init0 = 5'd1,
|
||||
init1 = 5'd2,
|
||||
init2 = 5'd3,
|
||||
init3 = 5'd4,
|
||||
init4 = 5'd5,
|
||||
init5 = 5'd6,
|
||||
init6 = 5'd7,
|
||||
init7 = 5'd8,
|
||||
init8 = 5'd9,
|
||||
init9 = 5'd10,
|
||||
init10 = 5'd11,
|
||||
init11 = 5'd12,
|
||||
read0 = 5'd13,
|
||||
read1 = 5'd14,
|
||||
write0 = 5'd15,
|
||||
write1 = 5'd16,
|
||||
last0 = 5'd17,
|
||||
last1 = 5'd18,
|
||||
last2 = 5'd19,
|
||||
last3 = 5'd20,
|
||||
wait0 = 5'd21,
|
||||
wait1 = 5'd22;
|
||||
|
||||
parameter ATA_ALTER = 5'b01110;
|
||||
parameter ATA_DEVCTRL = 5'b01110; /* bit [2] is a nIEN */
|
||||
parameter ATA_DATA = 5'b10000;
|
||||
parameter ATA_ERROR = 5'b10001;
|
||||
parameter ATA_FEATURE = 5'b10001;
|
||||
parameter ATA_SECCNT = 5'b10010;
|
||||
parameter ATA_SECNUM = 5'b10011; /* LBA[7:0] */
|
||||
parameter ATA_CYLLOW = 5'b10100; /* LBA[15:8] */
|
||||
parameter ATA_CYLHIGH = 5'b10101; /* LBA[23:16] */
|
||||
parameter ATA_DRVHEAD = 5'b10110; /* LBA + DRV + LBA[27:24] */
|
||||
parameter ATA_STATUS = 5'b10111;
|
||||
parameter ATA_COMMAND = 5'b10111;
|
||||
|
||||
parameter IDE_STATUS_BSY = 7;
|
||||
parameter IDE_STATUS_DRDY = 6;
|
||||
parameter IDE_STATUS_DWF = 5;
|
||||
parameter IDE_STATUS_DSC = 4;
|
||||
parameter IDE_STATUS_DRQ = 3;
|
||||
parameter IDE_STATUS_CORR = 2;
|
||||
parameter IDE_STATUS_IDX = 1;
|
||||
parameter IDE_STATUS_ERR = 0;
|
||||
|
||||
parameter ATA_CMD_READ = 16'h0020;
|
||||
parameter ATA_CMD_WRITE = 16'h0030;
|
||||
|
||||
reg ata_rd;
|
||||
reg ata_wr;
|
||||
reg [4:0] ata_addr;
|
||||
reg [15:0] ata_in;
|
||||
wire [15:0] ata_out;
|
||||
wire ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
reg [7:0] offset;
|
||||
reg [7:0] wc;
|
||||
|
||||
//
|
||||
ide ide1(.clk(clk), .reset(reset),
|
||||
.ata_rd(ata_rd), .ata_wr(ata_wr), .ata_addr(ata_addr),
|
||||
.ata_in(ata_in), .ata_out(ata_out), .ata_done(ata_done),
|
||||
.ide_data_bus(ide_data_bus),
|
||||
.ide_dior(ide_dior), .ide_diow(ide_diow),
|
||||
.ide_cs(ide_cs), .ide_da(ide_da));
|
||||
|
||||
//
|
||||
wire [23:0] lba = ide_lba;
|
||||
wire start = ide_read_req | ide_write_req;
|
||||
|
||||
|
||||
//
|
||||
alway @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
err <= 1'b0;
|
||||
done <= 1'b1;
|
||||
offset <= 0;
|
||||
wc <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (set_err)
|
||||
err <= 1'b1;
|
||||
else
|
||||
if (clear_err)
|
||||
err <= 1'b0;
|
||||
|
||||
if (set_done)
|
||||
done <= 1'b1;
|
||||
else
|
||||
if (clear_done)
|
||||
done <= 1'b0;
|
||||
|
||||
if (inc_offset)
|
||||
begin
|
||||
offset <= offset + 1;
|
||||
wc <= wc + 1;
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// ide state machine
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ide_state <= ready;
|
||||
else
|
||||
begin
|
||||
ide_state <= ide_state_next;
|
||||
end
|
||||
|
||||
always @(ide_state or lba or start or
|
||||
ata_done or ata_out or
|
||||
dma_data_in or dma_ack)
|
||||
begin
|
||||
ide_state_next = ide_state;
|
||||
|
||||
assert_int = 0;
|
||||
|
||||
set_err = 0;
|
||||
clear_err = 0;
|
||||
|
||||
set_done = 0;
|
||||
clear_done = 0;
|
||||
|
||||
inc_offset = 0;
|
||||
|
||||
ata_rd = 0;
|
||||
ata_wr = 0;
|
||||
ata_addr = 0;
|
||||
ata_in = 0;
|
||||
|
||||
buffer_rd = 0;
|
||||
buffer_wr = 0;
|
||||
buffer_addr = 0;
|
||||
buffer_out = 0;
|
||||
|
||||
case (ide_state)
|
||||
ready:
|
||||
begin
|
||||
if (start)
|
||||
begin
|
||||
ide_state_next = init0;
|
||||
$display("ide_disk: XXX go!");
|
||||
end
|
||||
end
|
||||
|
||||
init0:
|
||||
begin
|
||||
clear_done = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init1;
|
||||
end
|
||||
|
||||
init1:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040;
|
||||
if (ata_done)
|
||||
ide_state_next = wait0;
|
||||
end
|
||||
|
||||
wait0:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init2;
|
||||
//$display("ide_disk: XXX wait0");
|
||||
end
|
||||
|
||||
init2:
|
||||
begin
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init3;
|
||||
end
|
||||
|
||||
init3:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DEVCTRL;
|
||||
ata_in = 16'h0002; // nIEN
|
||||
if (ata_done)
|
||||
ide_state_next = init4;
|
||||
end
|
||||
|
||||
init4:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECCNT;
|
||||
ata_in = { 8'b0, 8'd1 };
|
||||
if (ata_done)
|
||||
ide_state_next = init5;
|
||||
end
|
||||
|
||||
init5:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECNUM;
|
||||
ata_in = {8'b0, lba[7:0]}; // LBA[7:0]
|
||||
if (ata_done)
|
||||
ide_state_next = init6;
|
||||
end
|
||||
|
||||
init6:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLLOW;
|
||||
ata_in = {8'b0, lba[15:8]}; // LBA[15:8]
|
||||
if (ata_done)
|
||||
ide_state_next = init7;
|
||||
end
|
||||
|
||||
|
||||
init7:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLHIGH;
|
||||
ata_in = lba[23:16]; // LBA[23:16]
|
||||
if (ata_done)
|
||||
ide_state_next = init8;
|
||||
end
|
||||
|
||||
init8:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040; // LBA[27:24] + LBA
|
||||
if (ata_done)
|
||||
ide_state_next = init9;
|
||||
end
|
||||
|
||||
init9:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_COMMAND;
|
||||
ata_in = ide_write_req ? ATA_CMD_WRITE :
|
||||
ide_read_req ? ATA_CMD_READ : 16'b0;
|
||||
if (ata_done)
|
||||
ide_state_next = wait1;
|
||||
end
|
||||
|
||||
wait1:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init10;
|
||||
end
|
||||
|
||||
init10:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = init11;
|
||||
end
|
||||
|
||||
init11:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
|
||||
//if (ata_done) $display("ide_disk: XXX init11 ata_out %x", ata_out);
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRQ])
|
||||
begin
|
||||
if (ide_write_req)
|
||||
ide_state_next = write0;
|
||||
else
|
||||
if (ide_read_req)
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
if (ata_out[IDE_STATUS_ERR])
|
||||
set_err = 1;
|
||||
end
|
||||
|
||||
read0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_DATA;
|
||||
|
||||
if (ata_done)
|
||||
begin
|
||||
inc_offset = 1;
|
||||
ide_state_next = read1;
|
||||
end
|
||||
end
|
||||
|
||||
read1:
|
||||
begin
|
||||
//buffer write
|
||||
buffer_addr = offset;
|
||||
buffer_out = ata_out;
|
||||
|
||||
if (0) $display("read1: XXX ata_out %o, buffer_addr %o",
|
||||
ata_out, buffer_addr);
|
||||
|
||||
buffer_wr = 1;
|
||||
inc_offset = 1;
|
||||
|
||||
if (wc == 16'h0000)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
write0:
|
||||
begin
|
||||
//buffer read
|
||||
buffer_addr = offset;
|
||||
buffer_rd = 1;
|
||||
|
||||
ata_in = dma_data_in;
|
||||
inc_offset = 1;
|
||||
ide_state_next = write1;
|
||||
end
|
||||
|
||||
write1:
|
||||
begin
|
||||
if (wc == 0)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = write0;
|
||||
end
|
||||
|
||||
last0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = last1;
|
||||
end
|
||||
|
||||
last1:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
if (ata_done)
|
||||
ide_state_next = last2;
|
||||
end
|
||||
|
||||
last2:
|
||||
begin
|
||||
clear_err = 1;
|
||||
set_done = 1;
|
||||
ide_state_next = last3;
|
||||
end
|
||||
|
||||
last3:
|
||||
begin
|
||||
ide_state_next = ready;
|
||||
$display("ide_disk: XXX last3, done");
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -290,7 +290,7 @@ will process the information.
|
||||
// read from ram
|
||||
DB_begin_xfer_write:
|
||||
ma_out = dma_addr
|
||||
mb_out = buffer_out
|
||||
buffer_hold <= ram_in
|
||||
ram_read_req = 1
|
||||
if ram_done db_next_state = DB_check_xfer_write;
|
||||
|
||||
@@ -454,6 +454,7 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
reg buffer_dirty;
|
||||
|
||||
reg [11:0] buffer_hold;
|
||||
wire [11:0] buffer_out;
|
||||
|
||||
wire buffer_matches_DMA;
|
||||
wire buffer_rd;
|
||||
@@ -474,6 +475,13 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
assign buffer_addr = disk_addr[7:0];
|
||||
|
||||
assign ide_done = 1;
|
||||
|
||||
// ide sector buffer
|
||||
ram_256x12 buffer(.A(buffer_addr),
|
||||
.DI(buffer_hold),
|
||||
.DO(buffer_out),
|
||||
.CE_N(1'b0),
|
||||
.WE_N(~buffer_wr));
|
||||
|
||||
// combinatorial
|
||||
always @(state or
|
||||
|
||||
29
rtl/ram_256x12.v
Normal file
29
rtl/ram_256x12.v
Normal file
@@ -0,0 +1,29 @@
|
||||
/* 256x12 static ram */
|
||||
module ram_256x12(A, DI, DO, CE_N, WE_N);
|
||||
|
||||
input[14:0] A;
|
||||
input [11:0] DI;
|
||||
input CE_N, WE_N;
|
||||
output [11:0] DO;
|
||||
|
||||
reg [11:0] ram [0:255];
|
||||
integer i;
|
||||
|
||||
initial
|
||||
begin
|
||||
for (i = 0; i < 256; i=i+1)
|
||||
ram[i] = 12'b0;
|
||||
end
|
||||
|
||||
always @(WE_N or CE_N or A or DI)
|
||||
begin
|
||||
if (WE_N == 0 && CE_N == 0)
|
||||
begin
|
||||
ram[ A ] = DI;
|
||||
end
|
||||
end
|
||||
|
||||
assign DO = ram[ A ];
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user