1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-05 23:54:41 +00:00

Archie: common FDC with the ST core

This commit is contained in:
Gyorgy Szombathelyi
2019-08-16 18:59:26 +02:00
parent 0beaddcc8e
commit 46bd0dd0c1
4 changed files with 865 additions and 638 deletions

View File

@@ -41,7 +41,7 @@ set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name TOP_LEVEL_ENTITY archimedes_mist_top
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:48:24 SEPTEMBER 20, 2014"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
@@ -136,7 +136,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_*
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to DRAM_*
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/sd.stp
set_global_assignment -name USE_SIGNALTAP_FILE output_files/fdc.stp
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_NCE_PIN OFF
@@ -171,12 +171,13 @@ set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
set_global_assignment -name FITTER_EFFORT "AUTO FIT"
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
set_instance_assignment -name FAST_INPUT_REGISTER ON -to DRAM_DQ[*]
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to DRAM_DQ[*]
set_global_assignment -name SEED 1
set_global_assignment -name ENABLE_DRC_SETTINGS OFF
set_location_assignment PLL_1 -to CLOCKS|altpll_component|auto_generated|pll1
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA
set_global_assignment -name VERILOG_FILE archimedes_mist_top.v
set_global_assignment -name SYSTEMVERILOG_FILE rgb2ypbpr.sv
set_global_assignment -name VERILOG_FILE sigma_delta_dac.v
@@ -226,5 +227,4 @@ set_global_assignment -name QIP_FILE rom_reconfig_36.qip
set_global_assignment -name QIP_FILE pll_vidc.qip
set_global_assignment -name SIGNALTAP_FILE output_files/vidc.stp
set_global_assignment -name SIGNALTAP_FILE output_files/sd.stp
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -297,63 +297,63 @@ podules PODULES(
.speed_i ( ioc_speed ),
.wb_cyc ( cpu_cyc & podules_en),
.wb_stb ( cpu_stb & podules_en),
.wb_we ( cpu_we & podules_en),
.wb_cyc ( cpu_cyc & podules_en ),
.wb_stb ( cpu_stb & podules_en ),
.wb_we ( cpu_we & podules_en ),
.wb_dat_o ( pod_dat_o ),
.wb_dat_i ( cpu_dat_o[15:0] ),
.wb_adr ( cpu_address[15:2] )
.wb_adr ( cpu_address[15:2] ),
);
wire [7:0] floppy_dat_o;
wire floppy_en = ioc_cs & ioc_select[1];
wire [7:0] floppy_dat_o;
wire floppy_en = ioc_cs & ioc_select[1];
// floppy drive signals.
wire [3:0] floppy_drive;
wire floppy_side;
wire floppy_motor;
wire floppy_inuse;
wire floppy_density;
wire floppy_reset;
fdc1772 FDC1772 (
.clkcpu ( CLKCPU_I ),
.clk8m_en ( ioc_clk8m_en ),
.wb_cyc ( cpu_cyc & floppy_en ),
.wb_stb ( cpu_stb & floppy_en ),
.wb_we ( cpu_we & floppy_en ),
.wb_dat_o ( floppy_dat_o ),
.wb_dat_i ( cpu_dat_o[23:16] ),
.wb_adr ( cpu_address[15:2] ),
.floppy_firq ( floppy_firq ),
.floppy_drq ( floppy_drq ),
.img_mounted ( img_mounted ),
.img_size ( img_size ),
.img_wp ( 0 ),
.sd_lba ( sd_lba ),
.sd_rd ( sd_rd ),
.sd_wr ( sd_wr ),
.sd_ack ( sd_ack ),
.sd_buff_addr ( sd_buff_addr ),
.sd_dout ( sd_dout ),
.sd_din ( sd_din ),
.sd_dout_strobe ( sd_dout_strobe ),
.sd_din_strobe ( sd_din_strobe ),
wire [3:0] floppy_drive;
wire floppy_side;
wire floppy_motor;
wire floppy_inuse;
wire floppy_density;
wire floppy_reset;
.floppy_drive ( floppy_drive ),
.floppy_motor ( floppy_motor ),
.floppy_inuse ( floppy_inuse ),
.floppy_side ( floppy_side ),
.floppy_density ( floppy_density ),
.floppy_reset ( floppy_reset )
wire fdc_sel = cpu_stb & cpu_cyc & floppy_en;
fdc1772 #(.CLK(42000000)) FDC1772 (
.clkcpu ( CLKCPU_I ),
.clk8m_en ( ioc_clk8m_en ),
.cpu_sel ( fdc_sel ),
.cpu_rw ( !cpu_we ),
.cpu_addr ( cpu_address[3:2] ),
.cpu_dout ( floppy_dat_o ),
.cpu_din ( cpu_dat_o[23:16] ),
.irq ( floppy_firq ),
.drq ( floppy_drq ),
.img_mounted ( img_mounted ),
.img_size ( img_size ),
.img_wp ( 0 ),
.sd_lba ( sd_lba ),
.sd_rd ( sd_rd ),
.sd_wr ( sd_wr ),
.sd_ack ( sd_ack ),
.sd_buff_addr ( sd_buff_addr ),
.sd_dout ( sd_dout ),
.sd_din ( sd_din ),
.sd_dout_strobe ( sd_dout_strobe ),
.sd_din_strobe ( sd_din_strobe ),
.floppy_drive ( floppy_drive ),
// .floppy_motor ( floppy_motor ),
// .floppy_inuse ( floppy_inuse ),
.floppy_side ( floppy_side ),
// .floppy_density ( floppy_density ),
.floppy_reset ( floppy_reset )
);
wire [7:0] latches_dat_o;
wire latches_en = ioc_cs & ioc_select[5] & (ioc_speed == 2'd2);

File diff suppressed because it is too large Load Diff

View File

@@ -25,9 +25,15 @@ module floppy (
input step_in,
input step_out,
input [10:0] sector_len,
input sector_base, // number of first sector on track (archie 0, dos 1)
input [4:0] spt, // sectors/track
input [9:0] sector_gap_len, // gap len/sector
input hd,
output dclk_en, // data clock enable
output [6:0] track, // number of track under head
output [3:0] sector, // number of sector under head, 0 = no sector
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
@@ -41,9 +47,10 @@ parameter SYS_CLK = 8000000;
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 RATE = 20'd250000;
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
@@ -53,34 +60,36 @@ localparam SECTOR_HDR_LEN = 4'd6; // GUESSED: Sector header is 6 bytes
localparam TRACKS = 8'd85; // max allowed track
// Archimedes specific values
localparam SECTOR_LEN = 11'd1024; // Default sector size is 1k on Archie ...
localparam SPT = 4'd5; // ... with 5 sectors per track
localparam SECTOR_BASE = 4'd0; // number of first sector on track (archie 0, dos 1)
//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)
// number of physical bytes per track
localparam BPT = RATE*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 == RATE) && (step_busy == 0);
assign ready = select && (rate == (hd ? RATEHD : RATEDD)) && (step_busy == 0);
// ================================================================
// ========================= INDEX PULSE ==========================
// ================================================================
// 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;
reg [18:0] index_pulse_cnt;
always @(posedge clk) begin
if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin
index <= 1'b0;
index_pulse_cnt <= 16'd0;
end else if(index_pulse_cnt == INDEX_PULSE_CYCLES-1)
index <= 1'b1;
else
index_pulse_cnt <= index_pulse_cnt + 16'd1;
if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin
index <= 1'b0;
index_pulse_cnt <= 19'd0;
end else if(index_pulse_cnt == INDEX_PULSE_CYCLES-1)
index <= 1'b1;
else
index_pulse_cnt <= index_pulse_cnt + 1'd1;
end
// ================================================================
// ======================= track handling =========================
// ================================================================
@@ -88,91 +97,90 @@ end
localparam[19:0] STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms
assign track = current_track;
reg [6:0] current_track = 7'd0;
reg [6:0] current_track /* verilator public */ = 7'd0;
reg step_inD;
reg step_outD;
reg [19:0] step_busy;
reg [19:0] step_busy /* verilator public */;
always @(posedge clk) begin
step_inD <= step_in;
step_outD <= step_out;
step_inD <= step_in;
step_outD <= step_out;
if(step_busy != 0)
step_busy <= step_busy - 18'd1;
if(step_busy != 0)
step_busy <= step_busy - 18'd1;
if(select) begin
// rising edge of step signal starts step
if(step_in && !step_inD) begin
if(current_track != 0) current_track <= current_track - 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
if(select) begin
// rising edge of step signal starts step
if(step_in && !step_inD) begin
if(current_track != 0) current_track <= current_track - 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
if(step_out && !step_outD) begin
if(current_track != TRACKS-1) current_track <= current_track + 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
end
if(step_out && !step_outD) begin
if(current_track != TRACKS-1) current_track <= current_track + 7'd1;
step_busy <= STEP_BUSY_CLKS;
end
end
end
// ================================================================
// ====================== sector handling =========================
// ================================================================
// track has BPT bytes
// SPT sectors are stored on the track
localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN);
//localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN);
assign sector = current_sector;
localparam SECTOR_STATE_GAP = 2'd0;
localparam SECTOR_STATE_HDR = 2'd1;
localparam SECTOR_STATE_DATA = 2'd2;
// we simulate an interleave of 1
reg [3:0] start_sector = SECTOR_BASE;
reg [4:0] start_sector = 4'd1;
reg [1:0] sec_state;
reg [9:0] sec_byte_cnt; // counting bytes within sectors
reg [3:0] current_sector = SECTOR_BASE;
reg [4:0] current_sector = 4'd1;
always @(posedge clk) begin
if (byte_clk_en) begin
if(index_pulse_start) begin
sec_byte_cnt <= SECTOR_GAP_LEN-1'd1;
sec_state <= SECTOR_STATE_GAP; // track starts with gap
current_sector <= start_sector; // track starts with sector 1
end else begin
if(sec_byte_cnt == 0) begin
case(sec_state)
SECTOR_STATE_GAP: begin
sec_state <= SECTOR_STATE_HDR;
sec_byte_cnt <= SECTOR_HDR_LEN-1'd1;
end
if(index_pulse_start) begin
sec_byte_cnt <= sector_gap_len-1'd1;
sec_state <= SECTOR_STATE_GAP; // track starts with gap
current_sector <= start_sector; // track starts with sector 1
end else begin
if(sec_byte_cnt == 0) begin
case(sec_state)
SECTOR_STATE_GAP: begin
sec_state <= SECTOR_STATE_HDR;
sec_byte_cnt <= SECTOR_HDR_LEN-1'd1;
end
SECTOR_STATE_HDR: begin
sec_state <= SECTOR_STATE_DATA;
sec_byte_cnt <= SECTOR_LEN-1'd1;
end
SECTOR_STATE_HDR: begin
sec_state <= SECTOR_STATE_DATA;
sec_byte_cnt <= sector_len-1'd1;
end
SECTOR_STATE_DATA: begin
sec_state <= SECTOR_STATE_GAP;
sec_byte_cnt <= SECTOR_GAP_LEN-1'd1;
if(current_sector == SECTOR_BASE+SPT-1)
current_sector <= SECTOR_BASE;
else
current_sector <= sector + 4'd1;
end
SECTOR_STATE_DATA: begin
sec_state <= SECTOR_STATE_GAP;
sec_byte_cnt <= sector_gap_len-1'd1;
if(current_sector == sector_base+spt-1)
current_sector <= sector_base;
else
current_sector <= sector + 1'd1;
end
default:
sec_state <= SECTOR_STATE_GAP;
default:
sec_state <= SECTOR_STATE_GAP;
endcase
end else
sec_byte_cnt <= sec_byte_cnt - 10'd1;
end
end
endcase
end else
sec_byte_cnt <= sec_byte_cnt - 10'd1;
end
end
end
// ================================================================
@@ -187,7 +195,7 @@ always @(posedge clk) begin
if (byte_clk_en) begin
index_pulse_start <= 1'b0;
if(byte_cnt == BPT-1) begin
if(byte_cnt == ((hd ? BPTHD : BPTDD)-1'd1)) begin
byte_cnt <= 0;
index_pulse_start <= 1'b1;
end else
@@ -217,41 +225,41 @@ end
localparam SPIN_UP_CLKS = SYS_CLK/1000*SPINUP;
localparam SPIN_DOWN_CLKS = SYS_CLK/1000*SPINDOWN;
reg [31:0] spin_up_counter;
// internal motor on signal that is only true if the drive is selected
wire motor_on_sel = motor_on && select;
// data rate determines rotation speed
reg [31:0] rate = 0;
reg [31:0] rate /* verilator public */ = 0;
reg motor_onD;
always @(posedge clk) begin
motor_onD <= motor_on_sel;
motor_onD <= motor_on_sel;
// reset spin_up counter whenever motor state changes
if(motor_onD != motor_on_sel)
spin_up_counter <= 32'd0;
else begin
spin_up_counter <= spin_up_counter + RATE;
// reset spin_up counter whenever motor state changes
if(motor_onD != motor_on_sel)
spin_up_counter <= 32'd0;
else begin
spin_up_counter <= spin_up_counter + (hd ? RATEHD : RATEDD);
if(motor_on_sel) begin
// spinning up
if(spin_up_counter > SPIN_UP_CLKS) begin
if(rate < RATE)
rate <= rate + 32'd1;
spin_up_counter <= spin_up_counter - (SPIN_UP_CLKS - RATE);
end
end else begin
// spinning down
if(spin_up_counter > SPIN_DOWN_CLKS) begin
if(rate > 0)
rate <= rate - 32'd1;
spin_up_counter <= spin_up_counter - (SPIN_DOWN_CLKS - RATE);
end
end // else: !if(motor_on)
end // else: !if(motor_onD != motor_on)
if(motor_on_sel) begin
// spinning up
if(spin_up_counter > SPIN_UP_CLKS) begin
if(rate < (hd ? RATEHD : RATEDD))
rate <= rate + 32'd1;
spin_up_counter <= spin_up_counter - (SPIN_UP_CLKS - (hd ? RATEHD : RATEDD));
end
end else begin
// spinning down
if(spin_up_counter > SPIN_DOWN_CLKS) begin
if(rate > 0)
rate <= rate - 32'd1;
spin_up_counter <= spin_up_counter - (SPIN_DOWN_CLKS - (hd ? RATEHD : RATEDD));
end
end // else: !if(motor_on)
end // else: !if(motor_onD != motor_on)
end
// Generate a data clock from the system clock. This depends on motor
// speed and reaches the full rate when the disk rotates at 300RPM. No
// valid data can be read until the disk has reached it's full speed.
@@ -259,13 +267,13 @@ reg data_clk;
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;
end
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;
end
endmodule