mirror of
https://github.com/MiSTer-devel/Archie_MiSTer.git
synced 2026-05-31 03:03:08 +00:00
Update FDC.
This commit is contained in:
@@ -344,7 +344,7 @@ wire floppy_density;
|
||||
wire floppy_reset;
|
||||
|
||||
wire fdc_sel = cpu_stb & cpu_cyc & floppy_en;
|
||||
fdc1772 #(CLKCPU) FDC1772 (
|
||||
fdc1772 #(.EXT_MOTOR(1'b1)) FDC1772 (
|
||||
.clkcpu ( CLKCPU_I ),
|
||||
.clk8m_en ( ioc_clk8m_en ),
|
||||
|
||||
@@ -370,7 +370,7 @@ fdc1772 #(CLKCPU) FDC1772 (
|
||||
.sd_dout_strobe ( sd_buff_wr ),
|
||||
|
||||
.floppy_drive ( floppy_drive ),
|
||||
// .floppy_motor ( floppy_motor ),
|
||||
.floppy_motor ( !floppy_motor ),
|
||||
// .floppy_inuse ( floppy_inuse ),
|
||||
.floppy_side ( floppy_side ),
|
||||
// .floppy_density ( floppy_density ),
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) floppy.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) fdc1772.v ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) fdc1772.sv ]
|
||||
|
||||
@@ -26,9 +26,12 @@ module fdc1772 (
|
||||
input clk8m_en,
|
||||
|
||||
// external set signals
|
||||
input [3:0] floppy_drive,
|
||||
input [W:0] floppy_drive,
|
||||
input floppy_side,
|
||||
input floppy_reset,
|
||||
output floppy_step,
|
||||
input floppy_motor,
|
||||
output floppy_ready,
|
||||
|
||||
// interrupts
|
||||
output reg irq,
|
||||
@@ -41,13 +44,13 @@ module fdc1772 (
|
||||
output reg [7:0] cpu_dout,
|
||||
|
||||
// place any signals that need to be passed up to the top after here.
|
||||
input [1:0] img_mounted, // signaling that new image has been mounted
|
||||
input [1:0] img_wp, // write protect
|
||||
input [W:0] img_mounted, // signaling that new image has been mounted
|
||||
input [W:0] img_wp, // write protect
|
||||
input img_ds, // double-sided image (for BBC Micro only)
|
||||
input [31:0] img_size, // size of image in bytes
|
||||
output reg[31:0] sd_lba,
|
||||
output reg [1:0] sd_rd,
|
||||
output reg [1:0] sd_wr,
|
||||
output reg [W:0] sd_rd,
|
||||
output reg [W:0] sd_wr,
|
||||
input sd_ack,
|
||||
input [7:0] sd_buff_addr,
|
||||
input [15:0] sd_dout,
|
||||
@@ -55,43 +58,34 @@ module fdc1772 (
|
||||
input sd_dout_strobe
|
||||
);
|
||||
|
||||
parameter CLK = 32000000;
|
||||
parameter CLK_EN = 16'd8000; // in kHz
|
||||
parameter SECTOR_SIZE_CODE = 2'd3; // sec size 0=128, 1=256, 2=512, 3=1024
|
||||
parameter SECTOR_BASE = 1'b0; // number of first sector on track (archie 0, dos 1)
|
||||
|
||||
localparam SECTOR_SIZE = 11'd128 << SECTOR_SIZE_CODE;
|
||||
parameter CLK_EN = 16'd8000; // in kHz
|
||||
parameter FD_NUM = 2; // number of supported floppies
|
||||
parameter MODEL = 2; // 0 - wd1770, 1 - fd1771, 2 - wd1772, 3 = wd1773/fd1793
|
||||
parameter EXT_MOTOR = 1'b0; // != 0 if motor is controlled externally by floppy_motor
|
||||
parameter INVERT_HEAD_RA = 1'b0; // != 0 - invert head in READ_ADDRESS reply
|
||||
|
||||
localparam IMG_ARCHIE = 0;
|
||||
localparam IMG_ST = 1;
|
||||
localparam IMG_BBC = 2; // SSD, DSD formats
|
||||
localparam IMG_TI99 = 3; // V9T9 format
|
||||
|
||||
parameter IMG_TYPE = IMG_ARCHIE;
|
||||
|
||||
localparam W = FD_NUM - 1;
|
||||
localparam WIDX = $clog2(FD_NUM);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// --------------------- IO controller image handling ----------------------
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
always @(*) begin
|
||||
case (SECTOR_SIZE_CODE)
|
||||
// archie
|
||||
3: sd_lba = {(16'd0 + (fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0], s_odd };
|
||||
// st
|
||||
2: sd_lba = ((fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0] - 1'd1;
|
||||
// bbc micro
|
||||
1: sd_lba = (((fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0]) >> 1;
|
||||
default: sd_lba = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
reg [1:0] floppy_ready = 0;
|
||||
|
||||
wire floppy_present = (floppy_drive == 4'b1110)?floppy_ready[0]:
|
||||
(floppy_drive == 4'b1101)?floppy_ready[1]:1'b0;
|
||||
|
||||
wire floppy_write_protected = (floppy_drive == 4'b1110)?img_wp[0]:
|
||||
(floppy_drive == 4'b1101)?img_wp[1]:1'b1;
|
||||
|
||||
reg [10:0] sector_len[2];
|
||||
reg [4:0] spt[2]; // sectors/track
|
||||
reg [9:0] gap_len[2]; // gap len/sector
|
||||
reg [1:0] doubleside;
|
||||
reg [1:0] hd;
|
||||
reg fm;
|
||||
reg [10:0] fdn_sector_len[FD_NUM];
|
||||
reg [4:0] fdn_spt[FD_NUM]; // sectors/track
|
||||
reg [9:0] fdn_gap_len[FD_NUM]; // gap len/sector
|
||||
reg fdn_doubleside[FD_NUM];
|
||||
reg fdn_hd[FD_NUM];
|
||||
reg fdn_fm[FD_NUM];
|
||||
reg fdn_present[FD_NUM];
|
||||
|
||||
reg [11:0] image_sectors;
|
||||
reg [11:0] image_sps; // sectors/side
|
||||
@@ -99,20 +93,34 @@ reg [4:0] image_spt; // sectors/track
|
||||
reg [9:0] image_gap_len;
|
||||
reg image_doubleside;
|
||||
wire image_hd = img_size[20];
|
||||
reg image_fm;
|
||||
|
||||
reg [1:0] sector_size_code; // sec size 0=128, 1=256, 2=512, 3=1024
|
||||
reg [10:0] sector_size;
|
||||
reg sector_base; // number of first sector on track (archie 0, dos 1)
|
||||
|
||||
always @(*) begin
|
||||
case (SECTOR_SIZE_CODE)
|
||||
3: begin
|
||||
case (IMG_TYPE)
|
||||
IMG_ARCHIE: begin
|
||||
// archie, 1024 bytes/sector
|
||||
fm = 0;
|
||||
sector_size_code = 2'd3;
|
||||
sector_base = 0;
|
||||
sd_lba = {(16'd0 + (fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0], s_odd };
|
||||
|
||||
image_fm = 0;
|
||||
image_sectors = img_size[21:10];
|
||||
image_doubleside = 1'b1;
|
||||
image_spt = image_hd ? 5'd10 : 5'd5;
|
||||
image_gap_len = 10'd220;
|
||||
|
||||
end
|
||||
2: begin
|
||||
IMG_ST: begin
|
||||
// this block is valid for the .st format (or similar arrangement), 512 bytes/sector
|
||||
fm = 0;
|
||||
sector_size_code = 2'd2;
|
||||
sector_base = 1;
|
||||
sd_lba = ((fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0] - 1'd1;
|
||||
|
||||
image_fm = 0;
|
||||
image_sectors = img_size[20:9];
|
||||
image_doubleside = 1'b0;
|
||||
image_sps = image_sectors;
|
||||
@@ -140,16 +148,32 @@ always @(*) begin
|
||||
default : image_gap_len = 10'd2;
|
||||
endcase;
|
||||
end
|
||||
1: begin
|
||||
// 256 bytes/sector single density (BBC SSD)
|
||||
fm = 1;
|
||||
IMG_BBC, IMG_TI99: begin
|
||||
// 256 bytes/sector single density (BBC SSD/DSD, TI99/4A)
|
||||
sector_size_code = 2'd1;
|
||||
sector_base = 0;
|
||||
if (IMG_TYPE == IMG_BBC) begin
|
||||
sd_lba = (((fd_spt*track[6:0]) << fd_doubleside) + (floppy_side ? 5'd0 : fd_spt) + sector[4:0]) >> 1;
|
||||
image_spt = 10;
|
||||
end else begin
|
||||
sd_lba = (fd_spt*(floppy_side ? track[5:0] : 79-track[5:0]) + sector[4:0]) >> 1;
|
||||
image_spt = 9;
|
||||
end
|
||||
|
||||
image_fm = 1;
|
||||
image_sectors = img_size[19:8];
|
||||
image_doubleside = img_ds;
|
||||
image_spt = 5'd10;
|
||||
if (img_ds)
|
||||
image_sps = image_sectors >> 1'b1;
|
||||
else
|
||||
image_sps = image_sectors;
|
||||
image_gap_len = 10'd50;
|
||||
end
|
||||
default: begin
|
||||
fm = 0;
|
||||
sector_size_code = 2'd0;
|
||||
sector_base = 0;
|
||||
sd_lba = 0;
|
||||
image_fm = 0;
|
||||
image_sectors = 0;
|
||||
image_doubleside = 0;
|
||||
image_spt = 0;
|
||||
@@ -157,27 +181,25 @@ always @(*) begin
|
||||
end
|
||||
|
||||
endcase
|
||||
|
||||
sector_size = 11'd128 << sector_size_code;
|
||||
end
|
||||
|
||||
always @(posedge clkcpu) begin
|
||||
reg [1:0] img_mountedD;
|
||||
|
||||
reg [W:0] img_mountedD;
|
||||
integer i;
|
||||
img_mountedD <= img_mounted;
|
||||
if (~img_mountedD[0] && img_mounted[0]) begin
|
||||
floppy_ready[0] <= |img_size;
|
||||
sector_len[0] <= SECTOR_SIZE;
|
||||
spt[0] <= image_spt;
|
||||
gap_len[0] <= image_gap_len;
|
||||
doubleside[0] <= image_doubleside;
|
||||
hd[0] <= image_hd;
|
||||
end
|
||||
if (~img_mountedD[1] && img_mounted[1]) begin
|
||||
floppy_ready[1] <= |img_size;
|
||||
sector_len[1] <= SECTOR_SIZE;
|
||||
spt[1] <= image_spt;
|
||||
gap_len[1] <= image_gap_len;
|
||||
doubleside[1] <= image_doubleside;
|
||||
hd[1] <= image_hd;
|
||||
|
||||
for(i = 0; i < FD_NUM; i = i+1'd1) begin
|
||||
if (~img_mountedD[i] && img_mounted[i]) begin
|
||||
fdn_present[i] <= |img_size;
|
||||
fdn_sector_len[i] <= sector_size;
|
||||
fdn_spt[i] <= image_spt;
|
||||
fdn_gap_len[i] <= image_gap_len;
|
||||
fdn_doubleside[i] <= image_doubleside;
|
||||
fdn_hd[i] <= image_hd;
|
||||
fdn_fm[i] <= image_fm;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -224,208 +246,78 @@ end
|
||||
// -------------------- virtual floppy drive mechanics ---------------------
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ------------------------------- floppy 0 --------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
wire fd0_index;
|
||||
wire fd0_ready;
|
||||
wire [6:0] fd0_track;
|
||||
wire [4:0] fd0_sector;
|
||||
wire fd0_sector_hdr;
|
||||
wire fd0_sector_data;
|
||||
wire fd0_dclk;
|
||||
wire fdn_index[FD_NUM];
|
||||
wire fdn_ready[FD_NUM];
|
||||
wire [6:0] fdn_track[FD_NUM];
|
||||
wire [4:0] fdn_sector[FD_NUM];
|
||||
wire fdn_sector_hdr[FD_NUM];
|
||||
wire fdn_sector_data[FD_NUM];
|
||||
wire fdn_dclk[FD_NUM];
|
||||
|
||||
floppy #(.SYS_CLK(CLK)) floppy0 (
|
||||
.clk ( clkcpu ),
|
||||
generate
|
||||
genvar i;
|
||||
|
||||
for(i=0; i < FD_NUM; i = i+1) begin :fdd
|
||||
|
||||
// control signals into floppy
|
||||
.select (!floppy_drive[0] ),
|
||||
.motor_on ( motor_on ),
|
||||
.step_in ( step_in ),
|
||||
.step_out ( step_out ),
|
||||
floppy #(.CLK_EN(CLK_EN)) floppy
|
||||
(
|
||||
.clk ( clkcpu ),
|
||||
.clk8m_en ( clk8m_en ),
|
||||
|
||||
// physical parameters
|
||||
.sector_len ( sector_len[0] ),
|
||||
.spt ( spt[0] ),
|
||||
.sector_gap_len ( gap_len[0] ),
|
||||
.sector_base ( SECTOR_BASE ),
|
||||
.hd ( hd[0] ),
|
||||
.fm ( fm ),
|
||||
// control signals into floppy
|
||||
.select ( fd_any && fdn == i ),
|
||||
.motor_on ( fd_motor ),
|
||||
.step_in ( step_in ),
|
||||
.step_out ( step_out ),
|
||||
|
||||
// status signals generated by floppy
|
||||
.dclk_en ( fd0_dclk ),
|
||||
.track ( fd0_track ),
|
||||
.sector ( fd0_sector ),
|
||||
.sector_hdr ( fd0_sector_hdr ),
|
||||
.sector_data ( fd0_sector_data ),
|
||||
.ready ( fd0_ready ),
|
||||
.index ( fd0_index )
|
||||
);
|
||||
// physical parameters
|
||||
.sector_len ( fdn_sector_len[i] ),
|
||||
.spt ( fdn_spt[i] ),
|
||||
.sector_gap_len ( fdn_gap_len[i] ),
|
||||
.sector_base ( sector_base ),
|
||||
.hd ( fdn_hd[i] ),
|
||||
.fm ( fdn_fm[i] ),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ------------------------------- floppy 1 --------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
wire fd1_index;
|
||||
wire fd1_ready;
|
||||
wire [6:0] fd1_track;
|
||||
wire [4:0] fd1_sector;
|
||||
wire fd1_sector_hdr;
|
||||
wire fd1_sector_data;
|
||||
wire fd1_dclk;
|
||||
|
||||
floppy #(.SYS_CLK(CLK)) floppy1 (
|
||||
.clk ( clkcpu ),
|
||||
|
||||
// control signals into floppy
|
||||
.select (!floppy_drive[1] ),
|
||||
.motor_on ( motor_on ),
|
||||
.step_in ( step_in ),
|
||||
.step_out ( step_out ),
|
||||
|
||||
// physical parameters
|
||||
.sector_len ( sector_len[1] ),
|
||||
.spt ( spt[1] ),
|
||||
.sector_gap_len ( gap_len[1] ),
|
||||
.sector_base ( SECTOR_BASE ),
|
||||
.hd ( hd[1] ),
|
||||
.fm ( fm ),
|
||||
|
||||
// status signals generated by floppy
|
||||
.dclk_en ( fd1_dclk ),
|
||||
.track ( fd1_track ),
|
||||
.sector ( fd1_sector ),
|
||||
.sector_hdr ( fd1_sector_hdr ),
|
||||
.sector_data ( fd1_sector_data ),
|
||||
.ready ( fd1_ready ),
|
||||
.index ( fd1_index )
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ------------------------------- floppy 2 --------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
wire fd2_index;
|
||||
wire fd2_ready;
|
||||
wire [6:0] fd2_track;
|
||||
wire [4:0] fd2_sector;
|
||||
wire fd2_sector_hdr;
|
||||
wire fd2_sector_data;
|
||||
wire fd2_dclk;
|
||||
|
||||
floppy #(.SYS_CLK(CLK)) floppy2 (
|
||||
.clk ( clkcpu ),
|
||||
|
||||
// control signals into floppy
|
||||
.select (!floppy_drive[2] ),
|
||||
.motor_on ( motor_on ),
|
||||
.step_in ( step_in ),
|
||||
.step_out ( step_out ),
|
||||
|
||||
// physical parameters
|
||||
.sector_len ( ),
|
||||
.spt ( ),
|
||||
.sector_gap_len ( ),
|
||||
.sector_base ( SECTOR_BASE ),
|
||||
.hd ( ),
|
||||
.fm ( fm ),
|
||||
|
||||
// status signals generated by floppy
|
||||
.dclk_en ( fd2_dclk ),
|
||||
.track ( fd2_track ),
|
||||
.sector ( fd2_sector ),
|
||||
.sector_hdr ( fd2_sector_hdr ),
|
||||
.sector_data ( fd2_sector_data ),
|
||||
.ready ( fd2_ready ),
|
||||
.index ( fd2_index )
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ------------------------------- floppy 3 --------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
wire fd3_index;
|
||||
wire fd3_ready;
|
||||
wire [6:0] fd3_track;
|
||||
wire [4:0] fd3_sector;
|
||||
wire fd3_sector_hdr;
|
||||
wire fd3_sector_data;
|
||||
wire fd3_dclk;
|
||||
|
||||
floppy #(.SYS_CLK(CLK)) floppy3 (
|
||||
.clk ( clkcpu ),
|
||||
|
||||
// control signals into floppy
|
||||
.select (!floppy_drive[3] ),
|
||||
.motor_on ( motor_on ),
|
||||
.step_in ( step_in ),
|
||||
.step_out ( step_out ),
|
||||
|
||||
// physical parameters
|
||||
.sector_len ( ),
|
||||
.spt ( ),
|
||||
.sector_gap_len ( ),
|
||||
.sector_base ( SECTOR_BASE ),
|
||||
.hd ( ),
|
||||
.fm ( fm ),
|
||||
|
||||
// status signals generated by floppy
|
||||
.dclk_en ( fd3_dclk ),
|
||||
.track ( fd3_track ),
|
||||
.sector ( fd3_sector ),
|
||||
.sector_hdr ( fd3_sector_hdr ),
|
||||
.sector_data ( fd3_sector_data ),
|
||||
.ready ( fd3_ready ),
|
||||
.index ( fd3_index )
|
||||
);
|
||||
// status signals generated by floppy
|
||||
.dclk_en ( fdn_dclk[i] ),
|
||||
.track ( fdn_track[i] ),
|
||||
.sector ( fdn_sector[i] ),
|
||||
.sector_hdr ( fdn_sector_hdr[i] ),
|
||||
.sector_data ( fdn_sector_data[i] ),
|
||||
.ready ( fdn_ready[i] ),
|
||||
.index ( fdn_index[i] )
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ----------------------------- floppy demux ------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
wire fd_index = (!floppy_drive[0])?fd0_index:
|
||||
(!floppy_drive[1])?fd1_index:
|
||||
(!floppy_drive[2])?fd2_index:
|
||||
(!floppy_drive[3])?fd3_index:
|
||||
1'b0;
|
||||
reg [WIDX:0] fdn;
|
||||
always begin
|
||||
integer i;
|
||||
|
||||
fdn = 0;
|
||||
for(i = FD_NUM-1; i >= 0; i = i - 1) if(!floppy_drive[i]) fdn = i[WIDX:0];
|
||||
end
|
||||
|
||||
wire fd_ready = (!floppy_drive[0])?fd0_ready:
|
||||
(!floppy_drive[1])?fd1_ready:
|
||||
(!floppy_drive[2])?fd2_ready:
|
||||
(!floppy_drive[3])?fd3_ready:
|
||||
1'b0;
|
||||
wire fd_any = ~&floppy_drive;
|
||||
|
||||
wire [6:0] fd_track = (!floppy_drive[0])?fd0_track:
|
||||
(!floppy_drive[1])?fd1_track:
|
||||
(!floppy_drive[2])?fd2_track:
|
||||
(!floppy_drive[3])?fd3_track:
|
||||
7'd0;
|
||||
wire fd_index = fd_any ? fdn_index[fdn] : 1'b0;
|
||||
wire fd_ready = fd_any ? fdn_ready[fdn] : 1'b0;
|
||||
wire [6:0] fd_track = fd_any ? fdn_track[fdn] : 7'd0;
|
||||
wire [4:0] fd_sector = fd_any ? fdn_sector[fdn] : 5'd0;
|
||||
wire fd_sector_hdr = fd_any ? fdn_sector_hdr[fdn] : 1'b0;
|
||||
//wire fd_sector_data = fd_any ? fdn_sector_data[fdn] : 1'b0;
|
||||
wire fd_dclk_en = fd_any ? fdn_dclk[fdn] : 1'b0;
|
||||
wire fd_present = fd_any ? fdn_present[fdn] : 1'b0;
|
||||
wire fd_writeprot = fd_any ? img_wp[fdn] : 1'b1;
|
||||
|
||||
wire [4:0] fd_sector = (!floppy_drive[0])?fd0_sector:
|
||||
(!floppy_drive[1])?fd1_sector:
|
||||
(!floppy_drive[2])?fd2_sector:
|
||||
(!floppy_drive[3])?fd3_sector:
|
||||
4'd0;
|
||||
wire fd_doubleside = fdn_doubleside[fdn];
|
||||
wire [4:0] fd_spt = fdn_spt[fdn];
|
||||
|
||||
wire fd_sector_hdr = (!floppy_drive[0])?fd0_sector_hdr:
|
||||
(!floppy_drive[1])?fd1_sector_hdr:
|
||||
(!floppy_drive[2])?fd2_sector_hdr:
|
||||
(!floppy_drive[3])?fd3_sector_hdr:
|
||||
1'b0;
|
||||
/*
|
||||
wire fd_sector_data = (!floppy_drive[0])?fd0_sector_data:
|
||||
(!floppy_drive[1])?fd1_sector_data:
|
||||
(!floppy_drive[2])?fd2_sector_data:
|
||||
(!floppy_drive[3])?fd3_sector_data:
|
||||
1'b0;
|
||||
*/
|
||||
wire fd_dclk_en = (!floppy_drive[0])?fd0_dclk:
|
||||
(!floppy_drive[1])?fd1_dclk:
|
||||
(!floppy_drive[2])?fd2_dclk:
|
||||
(!floppy_drive[3])?fd3_dclk:
|
||||
1'b0;
|
||||
|
||||
wire fd_doubleside = (!floppy_drive[0])?doubleside[0]:doubleside[1];
|
||||
wire [4:0] fd_spt = (!floppy_drive[0])?spt[0]:spt[1];
|
||||
|
||||
wire fd_track0 = (fd_track == 0);
|
||||
assign floppy_ready = fd_ready && fd_present;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ----------------------- internal state machines -------------------------
|
||||
@@ -445,6 +337,8 @@ reg busy /* verilator public */;
|
||||
reg step_in, step_out;
|
||||
reg [3:0] motor_spin_up_sequence /* verilator public */;
|
||||
|
||||
wire fd_motor = EXT_MOTOR ? floppy_motor : motor_on;
|
||||
|
||||
// consider spin up done either if the motor is not supposed to spin at all or
|
||||
// if it's supposed to run and has left the spin up sequence
|
||||
wire motor_spin_up_done = (!motor_on) || (motor_on && (motor_spin_up_sequence == 0));
|
||||
@@ -457,18 +351,24 @@ reg [15:0] step_pulse_cnt;
|
||||
|
||||
// the step rate is only valid for command type I
|
||||
wire [15:0] step_rate_clk =
|
||||
(cmd[1:0]==2'b00)?(16'd6*CLK_EN-1'd1): // 6ms
|
||||
(cmd[1:0]==2'b01)?(16'd12*CLK_EN-1'd1): // 12ms
|
||||
(cmd[1:0]==2'b10)?(16'd2*CLK_EN-1'd1): // 2ms
|
||||
(16'd3*CLK_EN-1'd1); // 3ms
|
||||
(cmd[1:0]==2'b00) ? (16'd6 *CLK_EN-1'd1): // 6ms
|
||||
(cmd[1:0]==2'b01) ? (16'd12*CLK_EN-1'd1): // 12ms
|
||||
(MODEL == 2 && cmd[1:0]==2'b10) ? (16'd2 *CLK_EN-1'd1): // 2ms
|
||||
(cmd[1:0]==2'b10) ? (16'd20*CLK_EN-1'd1): // 20ms
|
||||
(MODEL == 2) ? (16'd3 *CLK_EN-1'd1): // 3ms
|
||||
(16'd30*CLK_EN-1'd1); // 30ms
|
||||
|
||||
reg [15:0] step_rate_cnt;
|
||||
reg [23:0] delay_cnt;
|
||||
|
||||
assign floppy_step = step_in | step_out;
|
||||
|
||||
// flag indicating that a "step" is in progress
|
||||
wire step_busy = (step_rate_cnt != 0);
|
||||
wire delaying = (delay_cnt != 0);
|
||||
|
||||
wire fd_track0 = (fd_track == 0);
|
||||
|
||||
reg [7:0] step_to;
|
||||
reg RNF;
|
||||
reg sector_inc_strobe;
|
||||
@@ -554,7 +454,7 @@ always @(posedge clkcpu) begin
|
||||
|
||||
// ------------------------ TYPE I -------------------------
|
||||
if(cmd_type_1) begin
|
||||
if(!floppy_present) begin
|
||||
if(!fd_present) begin
|
||||
// no image selected -> send irq after 6 ms
|
||||
if (!notready_wait) begin
|
||||
delay_cnt <= 16'd6*CLK_EN;
|
||||
@@ -562,7 +462,6 @@ always @(posedge clkcpu) begin
|
||||
end else begin
|
||||
RNF <= 1'b1;
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
end else
|
||||
@@ -636,7 +535,6 @@ always @(posedge clkcpu) begin
|
||||
// finish
|
||||
3: begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
seek_state <= 0;
|
||||
end
|
||||
@@ -645,7 +543,7 @@ always @(posedge clkcpu) begin
|
||||
|
||||
// ------------------------ TYPE II -------------------------
|
||||
if(cmd_type_2) begin
|
||||
if(!floppy_present) begin
|
||||
if(!fd_present) begin
|
||||
// no image selected -> send irq after 6 ms
|
||||
if (!notready_wait) begin
|
||||
delay_cnt <= 16'd6*CLK_EN;
|
||||
@@ -653,12 +551,10 @@ always @(posedge clkcpu) begin
|
||||
end else begin
|
||||
RNF <= 1'b1;
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
end else if (sector_not_found) begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
RNF <= 1'b1;
|
||||
end else if (cmd[2] && !notready_wait) begin
|
||||
@@ -668,7 +564,7 @@ always @(posedge clkcpu) begin
|
||||
// read sector
|
||||
end else begin
|
||||
if(cmd[7:5] == 3'b100) begin
|
||||
if ((sector - SECTOR_BASE) >= fd_spt) begin
|
||||
if ((sector - sector_base) >= fd_spt) begin
|
||||
// wait 5 rotations (1 sec) before setting RNF
|
||||
sector_not_found <= 1'b1;
|
||||
delay_cnt <= 24'd1000 * CLK_EN;
|
||||
@@ -693,7 +589,6 @@ always @(posedge clkcpu) begin
|
||||
if (cmd[4]) sector_inc_strobe <= 1'b1; // multiple sector transfer
|
||||
else begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
end
|
||||
@@ -707,7 +602,7 @@ always @(posedge clkcpu) begin
|
||||
|
||||
// write sector
|
||||
if(cmd[7:5] == 3'b101) begin
|
||||
if ((sector - SECTOR_BASE) >= fd_spt) begin
|
||||
if ((sector - sector_base) >= fd_spt) begin
|
||||
// wait 5 rotations (1 sec) before setting RNF
|
||||
sector_not_found <= 1'b1;
|
||||
delay_cnt <= 24'd1000 * CLK_EN;
|
||||
@@ -715,12 +610,12 @@ always @(posedge clkcpu) begin
|
||||
case (data_transfer_state)
|
||||
2'b00: begin
|
||||
// pre-read phase
|
||||
if (SECTOR_SIZE_CODE < 2) sd_card_read <= 1;
|
||||
if (sector_size_code < 2) sd_card_read <= 1;
|
||||
data_transfer_state <= 2'b10;
|
||||
end
|
||||
2'b10: begin
|
||||
// CPU phase
|
||||
if (fifo_cpuptr == 0) data_transfer_start <= 1'b1;
|
||||
if (fifo_cpuptr == 0 && fd_ready && fd_sector_hdr && (fd_sector == sector)) data_transfer_start <= 1'b1;
|
||||
if (data_transfer_done) begin
|
||||
sd_card_write <= 1;
|
||||
data_transfer_state <= 2'b11;
|
||||
@@ -733,7 +628,6 @@ always @(posedge clkcpu) begin
|
||||
if (cmd[4]) sector_inc_strobe <= 1'b1; // multiple sector transfer
|
||||
else begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
end
|
||||
@@ -748,24 +642,21 @@ always @(posedge clkcpu) begin
|
||||
|
||||
// ------------------------ TYPE III -------------------------
|
||||
if(cmd_type_3) begin
|
||||
if(!floppy_present) begin
|
||||
if(!fd_present) begin
|
||||
// no image selected -> send irq immediately
|
||||
RNF <= 1'b1;
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end else begin
|
||||
// read track TODO: fake
|
||||
if(cmd[7:4] == 4'b1110) begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
|
||||
// write track TODO: fake
|
||||
if(cmd[7:4] == 4'b1111) begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
|
||||
@@ -777,7 +668,6 @@ always @(posedge clkcpu) begin
|
||||
|
||||
if(data_transfer_done) begin
|
||||
busy <= 1'b0;
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1'd1;
|
||||
irq_set <= 1'b1; // emit irq when command done
|
||||
end
|
||||
end
|
||||
@@ -791,17 +681,21 @@ always @(posedge clkcpu) begin
|
||||
irq_at_index <= 1'b0;
|
||||
if (irq_at_index) irq_set <= 1'b1;
|
||||
|
||||
// led motor timeout run once fdc is not busy anymore
|
||||
if(!busy) begin
|
||||
// let motor timeout run once fdc is not busy anymore
|
||||
if(!busy && motor_spin_up_done) begin
|
||||
if(motor_timeout_index != 0)
|
||||
motor_timeout_index <= motor_timeout_index - 4'd1;
|
||||
else
|
||||
else if(motor_on)
|
||||
motor_timeout_index <= MOTOR_IDLE_COUNTER;
|
||||
|
||||
if(motor_timeout_index == 1)
|
||||
motor_on <= 1'b0;
|
||||
end
|
||||
|
||||
if(motor_spin_up_sequence != 0)
|
||||
motor_spin_up_sequence <= motor_spin_up_sequence - 4'd1;
|
||||
end
|
||||
if(busy) motor_timeout_index <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -818,21 +712,21 @@ reg [10:0] fifo_cpuptr;
|
||||
reg [9:0] fifo_cpuptr_adj;
|
||||
wire [7:0] fifo_q;
|
||||
reg s_odd; //odd sector
|
||||
reg [8:0] fifo_sdptr;
|
||||
reg [9:0] fifo_sdptr;
|
||||
|
||||
always @(*) begin
|
||||
if (SECTOR_SIZE_CODE == 3)
|
||||
if (sector_size_code == 3)
|
||||
fifo_sdptr = { s_odd, sd_buff_addr };
|
||||
else
|
||||
fifo_sdptr = { 1'b0, sd_buff_addr };
|
||||
|
||||
if (SECTOR_SIZE_CODE == 1)
|
||||
fifo_cpuptr_adj = { 1'b0, sector[0], fifo_cpuptr[7:0] };
|
||||
if (sector_size_code == 1)
|
||||
fifo_cpuptr_adj = { 1'b0, (fd_spt[0] & (track[0] ^ !floppy_side)) ^ sector[0], fifo_cpuptr[7:0] };
|
||||
else
|
||||
fifo_cpuptr_adj = fifo_cpuptr[9:0];
|
||||
end
|
||||
|
||||
dpram_dif #(9,16,10,8) fifo
|
||||
fdc1772_dpram #(10) fifo
|
||||
(
|
||||
.clock(clkcpu),
|
||||
|
||||
@@ -871,32 +765,32 @@ always @(posedge clkcpu) begin
|
||||
begin
|
||||
s_odd <= 1'b0;
|
||||
if (~sd_card_readD & sd_card_read) begin
|
||||
sd_rd <= ~{ floppy_drive[1], floppy_drive[0] };
|
||||
sd_rd[fdn] <= 1;
|
||||
sd_state <= SD_READ;
|
||||
end
|
||||
else if (~sd_card_writeD & sd_card_write) begin
|
||||
sd_wr <= ~{ floppy_drive[1], floppy_drive[0] };
|
||||
sd_wr[fdn] <= 1;
|
||||
sd_state <= SD_WRITE;
|
||||
end
|
||||
end
|
||||
|
||||
SD_READ:
|
||||
if (sd_ackD & ~sd_ack) begin
|
||||
if (s_odd || SECTOR_SIZE_CODE != 3) begin
|
||||
if (s_odd || sector_size_code != 3) begin
|
||||
sd_state <= SD_IDLE;
|
||||
end else begin
|
||||
s_odd <= 1;
|
||||
sd_rd <= ~{ floppy_drive[1], floppy_drive[0] };
|
||||
sd_rd[fdn] <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
SD_WRITE:
|
||||
if (sd_ackD & ~sd_ack) begin
|
||||
if (s_odd || SECTOR_SIZE_CODE != 3) begin
|
||||
if (s_odd || sector_size_code != 3) begin
|
||||
sd_state <= SD_IDLE;
|
||||
end else begin
|
||||
s_odd <= 1;
|
||||
sd_wr <= ~{ floppy_drive[1], floppy_drive[0] };
|
||||
sd_wr[fdn] <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -905,16 +799,44 @@ always @(posedge clkcpu) begin
|
||||
end
|
||||
|
||||
// -------------------- CPU data read/write -----------------------
|
||||
reg data_in_strobe;
|
||||
reg data_in_valid;
|
||||
|
||||
function [15:0] crc;
|
||||
input [15:0] curcrc;
|
||||
input [7:0] val;
|
||||
reg [3:0] i;
|
||||
begin
|
||||
crc = {curcrc[15:8] ^ val, 8'h00};
|
||||
for (i = 0; i < 8; i=i+1'd1) begin
|
||||
if(crc[15]) begin
|
||||
crc = crc << 1;
|
||||
crc = crc ^ 16'h1021;
|
||||
end
|
||||
else crc = crc << 1;
|
||||
end
|
||||
crc = {curcrc[7:0] ^ crc[15:8], crc[7:0]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
always @(posedge clkcpu) begin
|
||||
reg data_transfer_startD;
|
||||
reg [10:0] data_transfer_cnt;
|
||||
reg [15:0] crcval;
|
||||
reg crc_en;
|
||||
|
||||
if (data_in_strobe) data_out <= data_in;
|
||||
crc_en <= 0;
|
||||
if(crc_en) crcval <= crc(crcval, data_out);
|
||||
|
||||
if (cpu_we && cpu_addr == FDC_REG_DATA) begin
|
||||
data_out <= data_in;
|
||||
data_in_valid <= 1;
|
||||
end
|
||||
|
||||
// reset fifo read pointer on reception of a new command or
|
||||
// when multi-sector transfer increments the sector number
|
||||
if(cmd_rx || sector_inc_strobe) begin
|
||||
data_in_valid <= 0;
|
||||
data_transfer_cnt <= 0;
|
||||
fifo_cpuptr <= 0;
|
||||
end
|
||||
@@ -926,15 +848,21 @@ always @(posedge clkcpu) begin
|
||||
if(~data_transfer_startD & data_transfer_start) begin
|
||||
|
||||
// read_address command has 6 data bytes
|
||||
if(cmd[7:4] == 4'b1100)
|
||||
if(cmd[7:4] == 4'b1100) begin
|
||||
crcval <= 16'hB230;
|
||||
data_transfer_cnt <= 11'd6+11'd1;
|
||||
end
|
||||
|
||||
// read/write sector has SECTOR_SIZE data bytes
|
||||
if(cmd[7:6] == 2'b10)
|
||||
data_transfer_cnt <= SECTOR_SIZE + 1'd1;
|
||||
data_transfer_cnt <= sector_size + 1'd1;
|
||||
|
||||
// write sector asserts drq earlier to fill up the data register in time
|
||||
if(cmd[7:5] == 3'b101) drq_set <= !data_in_valid;
|
||||
end
|
||||
|
||||
// write sector data arrived from CPU
|
||||
// advance fifo pointer when the write sector data consumed
|
||||
data_in_strobe <= 1'b0;
|
||||
if(cmd[7:5] == 3'b101 && data_in_strobe) fifo_cpuptr <= fifo_cpuptr + 1'd1;
|
||||
|
||||
if(fd_dclk_en) begin
|
||||
@@ -942,27 +870,32 @@ always @(posedge clkcpu) begin
|
||||
if(data_transfer_cnt != 1) begin
|
||||
data_lost <= 1'b0;
|
||||
if (drq) data_lost <= 1'b1;
|
||||
drq_set <= 1'b1;
|
||||
// raise drq, except when the last byte is already taken from the CPU for write
|
||||
if (cmd[7:5] != 3'b101 || data_transfer_cnt != 2) drq_set <= 1'b1;
|
||||
|
||||
// read_address
|
||||
if(cmd[7:4] == 4'b1100) begin
|
||||
case(data_transfer_cnt)
|
||||
7: data_out <= fd_track;
|
||||
6: data_out <= { 7'b0000000, floppy_side };
|
||||
5: data_out <= fd_sector;
|
||||
4: data_out <= SECTOR_SIZE_CODE; // TODO: sec size 0=128, 1=256, 2=512, 3=1024
|
||||
3: data_out <= 8'ha5;
|
||||
2: data_out <= 8'h5a;
|
||||
7: begin data_out <= fd_track; crc_en <= 1; end
|
||||
6: begin data_out <= { 7'b0000000, (INVERT_HEAD_RA != 0) ^ floppy_side }; crc_en <= 1; end
|
||||
5: begin data_out <= fd_sector; crc_en <= 1; end
|
||||
4: begin data_out <= sector_size_code[1:0]; crc_en <= 1; end // TODO: sec size 0=128, 1=256, 2=512, 3=1024
|
||||
3: data_out <= crcval[15:8];
|
||||
2: data_out <= crcval[7:0];
|
||||
endcase // case (data_read_cnt)
|
||||
end
|
||||
|
||||
// read sector
|
||||
if(cmd[7:5] == 3'b100) begin
|
||||
if(fifo_cpuptr != SECTOR_SIZE) begin
|
||||
data_out <= fifo_q;
|
||||
fifo_cpuptr <= fifo_cpuptr + 1'd1;
|
||||
end
|
||||
if(cmd[7:5] == 3'b100 && fifo_cpuptr != sector_size) begin
|
||||
data_out <= fifo_q;
|
||||
fifo_cpuptr <= fifo_cpuptr + 1'd1;
|
||||
end
|
||||
// write sector
|
||||
if(cmd[7:5] == 3'b101 && fifo_cpuptr != sector_size) begin
|
||||
data_in_strobe <= 1;
|
||||
data_in_valid <= 0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// count down and stop after last byte
|
||||
@@ -974,8 +907,8 @@ always @(posedge clkcpu) begin
|
||||
end
|
||||
|
||||
// the status byte
|
||||
wire [7:0] status = { motor_on,
|
||||
floppy_write_protected, // wrprot
|
||||
wire [7:0] status = { (MODEL == 1 || MODEL == 3) ? !floppy_ready : motor_on,
|
||||
(cmd[7:5] == 3'b101 || cmd[7:4] == 4'b1111 || cmd_type_1) && fd_writeprot, // wrprot (only for write!)
|
||||
cmd_type_1?motor_spin_up_done:1'b0, // data mark
|
||||
RNF, // seek error/record not found
|
||||
1'b0, // crc error
|
||||
@@ -1021,7 +954,6 @@ end
|
||||
// cpu register write
|
||||
reg cmd_rx /* verilator public */;
|
||||
reg cmd_rx_i;
|
||||
reg data_in_strobe;
|
||||
|
||||
always @(posedge clkcpu) begin
|
||||
if(!floppy_reset) begin
|
||||
@@ -1033,9 +965,7 @@ always @(posedge clkcpu) begin
|
||||
// reset state machines and counters
|
||||
cmd_rx_i <= 1'b0;
|
||||
cmd_rx <= 1'b0;
|
||||
data_in_strobe <= 0;
|
||||
end else begin
|
||||
data_in_strobe <= 0;
|
||||
|
||||
// cmd_rx is delayed to make sure all signals (the cmd!) are stable when
|
||||
// cmd_rx is evaluated
|
||||
@@ -1097,7 +1027,6 @@ always @(posedge clkcpu) begin
|
||||
sector <= cpu_din;
|
||||
|
||||
if(cpu_addr == FDC_REG_DATA) begin // data register
|
||||
data_in_strobe <= 1;
|
||||
data_in <= cpu_din;
|
||||
end
|
||||
end
|
||||
@@ -1110,3 +1039,42 @@ always @(posedge clkcpu) begin
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module fdc1772_dpram #(ADDRWIDTH=9)
|
||||
(
|
||||
input clock,
|
||||
|
||||
input [ADDRWIDTH-2:0] address_a,
|
||||
input [15:0] data_a,
|
||||
input wren_a,
|
||||
output reg [15:0] q_a,
|
||||
|
||||
input [ADDRWIDTH-1:0] address_b,
|
||||
input [7:0] data_b,
|
||||
input wren_b,
|
||||
output reg [7:0] q_b
|
||||
);
|
||||
|
||||
logic [1:0][7:0] ram[0:(1<<(ADDRWIDTH-1))-1];
|
||||
|
||||
always@(posedge clock) begin
|
||||
if(wren_a) begin
|
||||
ram[address_a] <= data_a;
|
||||
q_a <= data_a;
|
||||
end
|
||||
else begin
|
||||
q_a <= ram[address_a];
|
||||
end
|
||||
end
|
||||
|
||||
always@(posedge clock) begin
|
||||
if(wren_b) begin
|
||||
ram[address_b[ADDRWIDTH-1:1]][address_b[0]] <= data_b;
|
||||
q_b <= data_b;
|
||||
end
|
||||
else begin
|
||||
q_b <= ram[address_b[ADDRWIDTH-1:1]][address_b[0]];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -19,11 +19,13 @@
|
||||
|
||||
module floppy (
|
||||
// main clock
|
||||
input clk,
|
||||
input select,
|
||||
input motor_on,
|
||||
input step_in,
|
||||
input step_out,
|
||||
input clk,
|
||||
input clk8m_en,
|
||||
|
||||
input select,
|
||||
input motor_on,
|
||||
input step_in,
|
||||
input step_out,
|
||||
|
||||
input [10:0] sector_len,
|
||||
input sector_base, // number of first sector on track (archie 0, dos 1)
|
||||
@@ -32,38 +34,38 @@ module floppy (
|
||||
input hd,
|
||||
input fm,
|
||||
|
||||
output dclk_en, // data clock enable
|
||||
output dclk_en, // data clock enable
|
||||
output [6:0] track, // number of track under head
|
||||
output [4:0] sector, // number of sector under head, 0 = no sector
|
||||
output sector_hdr, // valid sector header under head
|
||||
output sector_data, // valid sector data under head
|
||||
output sector_hdr, // valid sector header under head
|
||||
output sector_data, // valid sector data under head
|
||||
|
||||
output ready, // drive is ready, data can be read
|
||||
output ready, // drive is ready, data can be read
|
||||
output reg index
|
||||
);
|
||||
|
||||
// The sysclock is the value all floppy timings are derived from.
|
||||
// Default: 8 MHz
|
||||
parameter SYS_CLK = 8000000;
|
||||
parameter CLK_EN = 8000;
|
||||
|
||||
assign sector_hdr = (sec_state == SECTOR_STATE_HDR);
|
||||
assign sector_data = (sec_state == SECTOR_STATE_DATA);
|
||||
|
||||
// a standard DD floppy has a data rate of 250kBit/s and rotates at 300RPM
|
||||
localparam RATESD = 20'd125000;
|
||||
localparam RATEDD = 20'd250000;
|
||||
localparam RATEHD = 20'd500000;
|
||||
localparam RPM = 10'd300;
|
||||
localparam STEPBUSY = 8'd18; // 18ms after step data can be read
|
||||
localparam SPINUP = 10'd500; // drive spins up in up to 800ms
|
||||
localparam SPINDOWN = 10'd300; // GUESSED: drive spins down in 300ms
|
||||
localparam INDEX_PULSE_LEN = 4'd5; // fd1036 data sheet says 1~8ms
|
||||
localparam SECTOR_HDR_LEN = 4'd6; // GUESSED: Sector header is 6 bytes
|
||||
localparam TRACKS = 8'd85; // max allowed track
|
||||
localparam RATESD = 125000;
|
||||
localparam RATEDD = 250000;
|
||||
localparam RATEHD = 500000;
|
||||
localparam RPM = 300;
|
||||
localparam STEPBUSY = 18; // 18ms after step data can be read
|
||||
localparam SPINUP = 500; // drive spins up in up to 800ms
|
||||
localparam SPINDOWN = 300; // GUESSED: drive spins down in 300ms
|
||||
localparam INDEX_PULSE_LEN = 5; // fd1036 data sheet says 1~8ms
|
||||
localparam SECTOR_HDR_LEN = 6; // GUESSED: Sector header is 6 bytes
|
||||
localparam TRACKS = 85; // max allowed track
|
||||
|
||||
// Archimedes specific values
|
||||
//localparam SECTOR_LEN = 11'd1024 // Default sector size is 1024 on Archie
|
||||
//localparam SECTOR_LEN = 11'd512; // Default sector size is 512 on ST ...
|
||||
//localparam SECTOR_LEN = 11'd1024 // Default sector size is 1024 on Archie
|
||||
//localparam SECTOR_LEN = 11'd512; // Default sector size is 512 on ST ...
|
||||
//localparam SPT = 4'd10; // ... with 5 sectors per track
|
||||
//localparam SECTOR_BASE = 4'd1; // number of first sector on track (archie 0, dos 1)
|
||||
|
||||
@@ -72,8 +74,8 @@ localparam BPTSD = RATESD*60/(8*RPM);
|
||||
localparam BPTDD = RATEDD*60/(8*RPM);
|
||||
localparam BPTHD = RATEHD*60/(8*RPM);
|
||||
|
||||
// report disk ready if it spins at full speed and head is not moving
|
||||
assign ready = select && (rate == (fm ? RATESD : hd ? RATEHD : RATEDD)) && (step_busy == 0);
|
||||
// report disk ready if it spins at full speed
|
||||
assign ready = select && (rate == (fm ? RATESD : hd ? RATEHD : RATEDD));
|
||||
|
||||
// ================================================================
|
||||
// ========================= INDEX PULSE ==========================
|
||||
@@ -81,9 +83,9 @@ assign ready = select && (rate == (fm ? RATESD : hd ? RATEHD : RATEDD)) && (step
|
||||
|
||||
// Index pulse generation. Pulse starts with the begin of index_pulse_start
|
||||
// and lasts INDEX_PULSE_CYCLES system clock cycles
|
||||
localparam INDEX_PULSE_CYCLES = INDEX_PULSE_LEN * SYS_CLK / 1000;
|
||||
localparam INDEX_PULSE_CYCLES = INDEX_PULSE_LEN * CLK_EN;
|
||||
reg [18:0] index_pulse_cnt;
|
||||
always @(posedge clk) begin
|
||||
always @(posedge clk) if(clk8m_en) begin
|
||||
if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin
|
||||
index <= 1'b0;
|
||||
index_pulse_cnt <= 19'd0;
|
||||
@@ -97,7 +99,7 @@ end
|
||||
// ======================= track handling =========================
|
||||
// ================================================================
|
||||
|
||||
localparam STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms
|
||||
localparam STEP_BUSY_CLKS = CLK_EN*STEPBUSY; // steprate is in ms
|
||||
|
||||
assign track = current_track;
|
||||
reg [6:0] current_track /* verilator public */ = 7'd0;
|
||||
@@ -110,7 +112,7 @@ always @(posedge clk) begin
|
||||
step_inD <= step_in;
|
||||
step_outD <= step_out;
|
||||
|
||||
if(step_busy != 0)
|
||||
if(clk8m_en && step_busy != 0)
|
||||
step_busy <= step_busy - 18'd1;
|
||||
|
||||
if(select) begin
|
||||
@@ -159,7 +161,7 @@ always @(posedge clk) begin
|
||||
case(sec_state)
|
||||
SECTOR_STATE_GAP: begin
|
||||
sec_state <= SECTOR_STATE_HDR;
|
||||
sec_byte_cnt <= SECTOR_HDR_LEN-1'd1;
|
||||
sec_byte_cnt <= SECTOR_HDR_LEN[9:0]-1'd1;
|
||||
end
|
||||
|
||||
SECTOR_STATE_HDR: begin
|
||||
@@ -225,8 +227,8 @@ end
|
||||
|
||||
// number of system clock cycles after which disk has reached
|
||||
// full speed
|
||||
localparam SPIN_UP_CLKS = SYS_CLK/1000*SPINUP;
|
||||
localparam SPIN_DOWN_CLKS = SYS_CLK/1000*SPINDOWN;
|
||||
localparam SPIN_UP_CLKS = CLK_EN*SPINUP;
|
||||
localparam SPIN_DOWN_CLKS = CLK_EN*SPINDOWN;
|
||||
reg [31:0] spin_up_counter;
|
||||
|
||||
// internal motor on signal that is only true if the drive is selected
|
||||
@@ -242,7 +244,7 @@ always @(posedge clk) begin
|
||||
// reset spin_up counter whenever motor state changes
|
||||
if(motor_onD != motor_on_sel)
|
||||
spin_up_counter <= 32'd0;
|
||||
else begin
|
||||
else if(clk8m_en) begin
|
||||
spin_up_counter <= spin_up_counter + (fm ? RATESD : hd ? RATEHD : RATEDD);
|
||||
|
||||
if(motor_on_sel) begin
|
||||
@@ -271,12 +273,14 @@ reg data_clk_en;
|
||||
reg [31:0] clk_cnt;
|
||||
always @(posedge clk) begin
|
||||
data_clk_en <= 0;
|
||||
if(clk_cnt + rate > SYS_CLK/2) begin
|
||||
clk_cnt <= clk_cnt - (SYS_CLK/2 - rate);
|
||||
data_clk <= !data_clk;
|
||||
if (~data_clk) data_clk_en <= 1;
|
||||
end else
|
||||
clk_cnt <= clk_cnt + rate;
|
||||
if(clk8m_en) begin
|
||||
if(clk_cnt + rate > CLK_EN*1000/2) begin
|
||||
clk_cnt <= clk_cnt - (CLK_EN*1000/2 - rate);
|
||||
data_clk <= !data_clk;
|
||||
if (~data_clk) data_clk_en <= 1;
|
||||
end else
|
||||
clk_cnt <= clk_cnt + rate;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user