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

Merge pull request #85 from gyurco/archie

[Archie] Use standard IO for FDC with full read/write support
This commit is contained in:
gyurco
2019-03-02 16:47:38 +01:00
committed by GitHub
5 changed files with 425 additions and 162 deletions

View File

@@ -274,8 +274,23 @@ wire CSync = ~(core_hs ^ core_vs);
assign VGA_HS = ((pixbaseclk_select[0] == pixbaseclk_select[1]) | ypbpr) ? CSync : core_hs;
assign VGA_VS = ((pixbaseclk_select[0] == pixbaseclk_select[1]) | ypbpr) ? 1'b1 : core_vs;
wire [31:0] sd_lba;
wire [1:0] sd_rd;
wire [1:0] sd_wr;
wire sd_ack;
wire sd_ack_conf;
wire sd_conf;
wire sd_sdhc = 1'b1;
wire [7:0] sd_dout;
wire sd_dout_strobe;
wire [7:0] sd_din;
wire sd_din_strobe;
wire [8:0] sd_buff_addr;
wire [1:0] img_mounted;
wire [31:0] img_size;
// de-multiplex spi outputs from user_io and data_io
assign SPI_DO = (CONF_DATA0==0)?user_io_sdo:(SPI_SS2==0)?data_io_sdo:1'bZ;
assign SPI_DO = (CONF_DATA0==0)?user_io_sdo:1'bZ;
wire user_io_sdo;
user_io user_io(
@@ -297,30 +312,34 @@ user_io user_io(
.kbd_out_data ( kbd_out_data ),
.kbd_out_strobe ( kbd_out_strobe ),
.kbd_in_data ( kbd_in_data ),
.kbd_in_strobe ( kbd_in_strobe )
.kbd_in_strobe ( kbd_in_strobe ),
.sd_lba ( sd_lba ),
.sd_rd ( sd_rd ),
.sd_wr ( sd_wr ),
.sd_ack ( sd_ack ),
.sd_ack_conf ( sd_ack_conf ),
.sd_conf ( sd_conf ),
.sd_sdhc ( sd_sdhc ),
.sd_dout ( sd_dout ),
.sd_dout_strobe ( sd_dout_strobe ),
.sd_din ( sd_din ),
.sd_din_strobe ( sd_din_strobe ),
.sd_buff_addr ( sd_buff_addr ),
.img_mounted ( img_mounted ),
.img_size ( img_size )
);
wire data_io_sdo;
wire [31:0] fdc_status_out;
wire [31:0] fdc_status_in;
wire [7:0] fdc_data_in;
wire fdc_data_in_strobe;
data_io # ( .START_ADDR(26'h40_0000) )
DATA_IO (
.sck ( SPI_SCK ),
.ss ( SPI_SS2 ),
.sdi ( SPI_DI ),
.sdo ( data_io_sdo ),
.downloading ( loader_active ),
.size ( ),
.fdc_status_out( fdc_status_out ),
.fdc_status_in ( fdc_status_in ),
.fdc_data_in_strobe ( fdc_data_in_strobe ),
.fdc_data_in ( fdc_data_in ),
// ram interface
// ram interface
.clk ( clk_32m ),
.wr ( loader_we ),
.a ( loader_addr ),
@@ -377,16 +396,24 @@ archimedes_top ARCHIMEDES(
.DEBUG_LED ( LED ),
.FDC_DIO_STATUS_OUT ( fdc_status_out ),
.FDC_DIO_STATUS_IN ( fdc_status_in ),
.FDC_DIN_STROBE ( fdc_data_in_strobe ),
.FDC_DIN ( fdc_data_in ),
.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 ),
.KBD_OUT_DATA ( kbd_out_data ),
.KBD_OUT_STROBE ( kbd_out_strobe ),
.KBD_IN_DATA ( kbd_in_data ),
.KBD_IN_STROBE ( kbd_in_strobe ),
.JOYSTICK0 ( ~{joyB[4], joyB[0], joyB[1], joyB[2], joyB[3]} ),
.JOYSTICK1 ( ~{joyA[4], joyA[0], joyA[1], joyA[2], joyA[3]} ),
.VIDBASECLK_O ( pixbaseclk_select ),

View File

@@ -28,17 +28,10 @@ module data_io #(parameter ADDR_WIDTH=24, START_ADDR = 0) (
input sck,
input ss,
input sdi,
output reg sdo,
output reg downloading, // signal indicating an active download
output [ADDR_WIDTH-1:0] size, // number of bytes in input buffer
// additional signals for floppy emulation
input [31:0] fdc_status_out,
output reg [31:0] fdc_status_in,
output reg fdc_data_in_strobe,
output reg [7:0] fdc_data_in,
// external ram interface
input clk,
output reg wr,
@@ -70,9 +63,6 @@ reg [ADDR_WIDTH-1:0] addr;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FDC_GET_STATUS = 8'h55;
localparam UIO_FDC_TX_DATA = 8'h56;
localparam UIO_FDC_SET_STATUS = 8'h57;
// data_io has its own SPI interface to the io controller
@@ -91,17 +81,6 @@ always@(posedge sck or posedge ss) begin
end
end
always@(negedge sck or posedge ss) begin
if(ss == 1) begin
sdo <= 1'bZ;
end else begin
if(cmd == UIO_FDC_GET_STATUS)
sdo <= fdc_status_out[{4-byte_cnt,~bit_cnt}];
else
sdo <= 1'b0;
end
end
// SPI receiver IO -> FPGA
reg spi_receiver_strobe_r = 0;
@@ -135,7 +114,6 @@ always @(posedge clk) begin
reg [7:0] acmd;
reg [3:0] abyte_cnt; // counts bytes
fdc_data_in_strobe <= 0;
wr <= 0;
//synchronize between SPI and sys clock domains
@@ -176,23 +154,7 @@ always @(posedge clk) begin
data <= spi_byte_in;
wr <= 1;
end
// command 0x56: UIO_FDC_TX_DATA
UIO_FDC_TX_DATA:
begin
fdc_data_in_strobe <= 1'b1;
fdc_data_in <= spi_byte_in;
end
// command 0x57: UIO_FDC_SET_STATUS
UIO_FDC_SET_STATUS:
begin
if (abyte_cnt == 1) fdc_status_in[31:24] <= spi_byte_in;
if (abyte_cnt == 2) fdc_status_in[23:16] <= spi_byte_in;
if (abyte_cnt == 3) fdc_status_in[15: 8] <= spi_byte_in;
if (abyte_cnt == 4) fdc_status_in[ 7: 0] <= spi_byte_in;
end
endcase
endcase;
end
end
end

View File

@@ -41,7 +41,24 @@ module user_io (
output reg kbd_in_strobe,
output [1:0] BUTTONS,
output [1:0] SWITCHES
output [1:0] SWITCHES,
// connection to sd card emulation
input [31:0] sd_lba,
input [1:0] sd_rd,
input [1:0] sd_wr,
output reg sd_ack,
output reg sd_ack_conf,
input sd_conf,
input sd_sdhc,
output reg [7:0] sd_dout, // valid on rising edge of sd_dout_strobe
output reg sd_dout_strobe,
input [7:0] sd_din,
output reg sd_din_strobe,
output reg [8:0] sd_buff_addr,
output reg [1:0] img_mounted, //rising edge if a new image is mounted
output reg[31:0] img_size // size of image in bytes
);
reg [6:0] sbuf;
@@ -85,15 +102,24 @@ always@(posedge SPI_CLK or posedge SPI_SS_IO) begin
end
end
wire drive_sel = sd_rd[1] | sd_wr[1];
always@(negedge SPI_CLK or posedge SPI_SS_IO) begin
reg [7:0] kbd_out_status;
reg [7:0] kbd_out_data_r;
reg [7:0] kbd_out_status;
reg [7:0] kbd_out_data_r;
reg [31:0] sd_lba_r;
reg [7:0] drive_sel_r;
reg [7:0] sd_cmd;
reg [7:0] sd_din_r;
if(SPI_SS_IO == 1) begin
SPI_MISO <= 1'bZ;
end else begin
kbd_out_status <= { 4'ha, 3'b000, kbd_out_data_available };
kbd_out_data_r <= kbd_out_data;
sd_cmd <= { 4'h6, sd_conf, sd_sdhc, sd_wr[drive_sel], sd_rd[drive_sel] };
if(&bit_cnt) sd_din_r <= sd_din;
// first byte returned is always core type, further bytes are
// command dependent
if(byte_cnt == 0) begin
@@ -104,6 +130,20 @@ always@(negedge SPI_CLK or posedge SPI_SS_IO) begin
if(byte_cnt == 1) SPI_MISO <= kbd_out_status[~bit_cnt];
else SPI_MISO <= kbd_out_data_r[~bit_cnt];
end
// reading sd card status
if(cmd == 8'h16) begin
if(byte_cnt == 1) begin
SPI_MISO <= sd_cmd[~bit_cnt];
sd_lba_r <= sd_lba;
drive_sel_r <= {6'b0, drive_sel};
end
else if(byte_cnt == 2) SPI_MISO <= drive_sel_r[~bit_cnt];
else if(byte_cnt < 7) SPI_MISO <= sd_lba_r[{6-byte_cnt, ~bit_cnt}];
end
// reading sd card write data
if(cmd == 8'h18) SPI_MISO <= sd_din_r[~bit_cnt];
end
end
end
@@ -180,4 +220,91 @@ always @(posedge clk_sys) begin
if (kbd_out_strobe) kbd_out_data_available <= 1;
end
// Process SD-card related bytes from SPI
always @(posedge clk_sys) begin
reg spi_receiver_strobe;
reg spi_transfer_end;
reg spi_receiver_strobeD;
reg spi_transfer_endD;
reg sd_wrD;
reg [7:0] acmd;
reg [7:0] abyte_cnt; // counts bytes
//synchronize between SPI and sd clock domains
spi_receiver_strobeD <= spi_receiver_strobe_r;
spi_receiver_strobe <= spi_receiver_strobeD;
spi_transfer_endD <= spi_transfer_end_r;
spi_transfer_end <= spi_transfer_endD;
if(sd_dout_strobe) begin
sd_dout_strobe<= 0;
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
end
sd_din_strobe<= 0;
sd_wrD <= sd_wr;
// fetch the first byte immediately after the write command seen
if (~sd_wrD & sd_wr) begin
sd_buff_addr <= 0;
sd_din_strobe <= 1;
end
img_mounted <= 0;
if (~spi_transfer_endD & spi_transfer_end) begin
abyte_cnt <= 8'd0;
sd_ack <= 1'b0;
sd_ack_conf <= 1'b0;
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
sd_buff_addr<= 0;
end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin
if(~&abyte_cnt)
abyte_cnt <= abyte_cnt + 8'd1;
if(abyte_cnt == 0) begin
acmd <= spi_byte_in;
if((spi_byte_in == 8'h17) || (spi_byte_in == 8'h18))
sd_ack <= 1'b1;
if (spi_byte_in == 8'h18) begin
sd_din_strobe <= 1'b1;
sd_buff_addr <= sd_buff_addr + 1'b1;
end
end else begin
case(acmd)
// send sector IO -> FPGA
8'h17: begin
// flag that download begins
sd_dout_strobe <= 1'b1;
sd_dout <= spi_byte_in;
end
8'h18: begin
sd_din_strobe <= 1'b1;
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
end
// send SD config IO -> FPGA
8'h19: begin
// flag that download begins
sd_dout_strobe <= 1'b1;
sd_ack_conf <= 1'b1;
sd_dout <= spi_byte_in;
end
8'h1c: img_mounted[spi_byte_in[0]] <= 1;
// send image info
8'h1d: if(abyte_cnt<5) img_size[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
endcase
end
end
end
endmodule

View File

@@ -67,11 +67,19 @@ module archimedes_top(
output DEBUG_LED,
// floppy connections to external controller
output [31:0] FDC_DIO_STATUS_OUT,
input [31:0] FDC_DIO_STATUS_IN,
input [7:0] FDC_DIN,
input FDC_DIN_STROBE,
input [1:0] img_mounted, // signaling that new image has been mounted
input img_wp, // write protect. latched at img_mounted
input [31:0] img_size, // size of image in bytes
output [31:0] sd_lba,
output [1:0] sd_rd,
output [1:0] sd_wr,
input sd_ack,
input [8:0] sd_buff_addr,
input [7:0] sd_dout,
output [7:0] sd_din,
input sd_dout_strobe,
input sd_din_strobe,
// connection to keyboard controller
output [7:0] KBD_OUT_DATA,
output KBD_OUT_STROBE,
@@ -324,17 +332,25 @@ fdc1772 FDC1772 (
.floppy_firq ( floppy_firq ),
.floppy_drq ( floppy_drq ),
.dio_status_out( FDC_DIO_STATUS_OUT ),
.dio_status_in ( FDC_DIO_STATUS_IN ),
.dio_in_strobe ( FDC_DIN_STROBE ),
.dio_in ( FDC_DIN ),
.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_density ( floppy_density ),
.floppy_reset ( floppy_reset )
);

View File

@@ -48,36 +48,52 @@ module fdc1772 (
output reg [7:0] wb_dat_o, // bd
// place any signals that need to be passed up to the top after here.
output [31:0] dio_status_out,
input [31:0] dio_status_in,
input dio_in_strobe,
input [7:0] dio_in
input [1:0] img_mounted, // signaling that new image has been mounted
input img_wp, // write protect. latched at img_mounted
input [31:0] img_size, // size of image in bytes
output [31:0] sd_lba,
output reg [1:0] sd_rd,
output reg [1:0] sd_wr,
input sd_ack,
input [8:0] sd_buff_addr,
input [7:0] sd_dout,
output [7:0] sd_din,
input sd_dout_strobe,
input sd_din_strobe
);
localparam CLK = 8000000;
localparam CLK = 32000000;
localparam CLK_EN = 8000000;
// -------------------------------------------------------------------------
// --------------------- IO controller status handling ---------------------
// -------------------------------------------------------------------------
// sector only needs 4 bits and track only needs 7 bits. We thus encode side and
// floppy_drive into the upper bits
assign dio_status_out = { 5'b10100, fifo_rptr==0, fifo_wptr==0, busy,
cmd, floppy_side, track[6:0], floppy_drive, sector[3:0] };
assign sd_lba = { 4'd10*track[6:0] + (floppy_side ? 0 : 4'd5) + sector[3:0], s_odd };
// input status encodes information about all four possible floppy drives
// in 4*8 bits
wire [7:0] floppy_status =
(floppy_drive == 4'b1110)?dio_status_in[31:24]:
(floppy_drive == 4'b1101)?dio_status_in[23:16]:
(floppy_drive == 4'b1011)?dio_status_in[15:8]:
(floppy_drive == 4'b0111)?dio_status_in[7:0]:
8'h00;
reg [1:0] floppy_ready = 0;
reg [1:0] floppy_wp = 1;
wire floppy_present = floppy_status[0];
wire floppy_write_protected = 1'b1; // will be floppy_status[1] in the future
wire floppy_present = (floppy_drive == 4'b1110)?floppy_ready[0]:
(floppy_drive == 4'b1101)?floppy_ready[1]:0;
wire floppy_write_protected = (floppy_drive == 4'b1110)?floppy_wp[0]:
(floppy_drive == 4'b1101)?floppy_wp[1]:1;
always @(posedge clkcpu) begin
reg [1:0] img_mountedD;
img_mountedD <= img_mounted;
if (~img_mountedD[0] && img_mounted[0]) begin
floppy_ready[0] <= |img_size;
floppy_wp[0] <= img_wp;
end
if (~img_mountedD[1] && img_mounted[1]) begin
floppy_ready[1] <= |img_size;
floppy_wp[1] <= img_wp;
end
end
// -------------------------------------------------------------------------
// ---------------------------- IRQ/DRQ handling ---------------------------
// -------------------------------------------------------------------------
@@ -102,12 +118,11 @@ assign floppy_firq = irq;
reg drq;
reg drq_set;
reg cpu_read_data;
reg cpu_rw_data;
always @(posedge clkcpu)
cpu_read_data <= wb_stb && wb_cyc && !wb_we &&
(wb_adr[3:2] == FDC_REG_DATA);
cpu_rw_data <= wb_stb && wb_cyc && (wb_adr[3:2] == FDC_REG_DATA);
wire drq_clr = !floppy_reset || cpu_read_data;
wire drq_clr = !floppy_reset || cpu_rw_data;
always @(posedge clkcpu or posedge drq_clr) begin
if(drq_clr) drq <= 1'b0;
@@ -131,7 +146,7 @@ wire fd0_sector_hdr;
wire fd0_sector_data;
wire fd0_dclk;
floppy #(.SYS_CLK(32000000)) floppy0 (
floppy #(.SYS_CLK(CLK)) floppy0 (
.clk ( clkcpu ),
// control signals into floppy
@@ -161,7 +176,7 @@ wire fd1_sector_hdr;
wire fd1_sector_data;
wire fd1_dclk;
floppy #(.SYS_CLK(32000000)) floppy1 (
floppy #(.SYS_CLK(CLK)) floppy1 (
.clk ( clkcpu ),
// control signals into floppy
@@ -191,7 +206,7 @@ wire fd2_sector_hdr;
wire fd2_sector_data;
wire fd2_dclk;
floppy #(.SYS_CLK(32000000)) floppy2 (
floppy #(.SYS_CLK(CLK)) floppy2 (
.clk ( clkcpu ),
// control signals into floppy
@@ -221,7 +236,7 @@ wire fd3_sector_hdr;
wire fd3_sector_data;
wire fd3_dclk;
floppy #(.SYS_CLK(32000000)) floppy3 (
floppy #(.SYS_CLK(CLK)) floppy3 (
.clk ( clkcpu ),
// control signals into floppy
@@ -313,15 +328,15 @@ wire motor_spin_up_done = (!motor_on) || (motor_on && (motor_spin_up_sequence ==
// ---------------------------- step handling ------------------------------
localparam STEP_PULSE_LEN = 1;
localparam STEP_PULSE_CLKS = (STEP_PULSE_LEN * CLK)/1000;
localparam STEP_PULSE_CLKS = (STEP_PULSE_LEN * CLK_EN)/1000;
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)?(2*CLK/1000-1): // 2ms
(cmd[1:0]==2'b01)?(3*CLK/1000-1): // 3ms
(cmd[1:0]==2'b10)?(5*CLK/1000-1): // 5ms
(6*CLK/1000-1); // 6ms
(cmd[1:0]==2'b00)?(2*CLK_EN/1000-1): // 2ms
(cmd[1:0]==2'b01)?(3*CLK_EN/1000-1): // 3ms
(cmd[1:0]==2'b10)?(5*CLK_EN/1000-1): // 5ms
(6*CLK_EN/1000-1); // 6ms
reg [15:0] step_rate_cnt;
@@ -330,19 +345,20 @@ wire step_busy = (step_rate_cnt != 0);
reg [7:0] step_to;
always @(posedge clkcpu) begin
irq_set <= 0;
sd_card_read <= 0;
sd_card_write <= 0;
if(!floppy_reset) begin
motor_on <= 1'b0;
busy <= 1'b0;
step_in <= 1'b0;
step_out <= 1'b0;
irq_set <= 1'b0;
data_read_start_set <= 1'b0;
data_read_done_clr <= 1'b0;
data_transfer_start <= 1'b0;
end else if (clk8m_en) begin
irq_set <= 1'b0;
data_read_start_set <= 1'b0;
data_read_done_clr <= 1'b0;
data_transfer_start <= 1'b0;
// disable step signal after 1 msec
if(step_pulse_cnt != 0)
@@ -411,16 +427,27 @@ always @(posedge clkcpu) begin
end else begin
// read sector
if(cmd[7:5] == 3'b100) begin
if (sd_state == SD_IDLE && fifo_cpuptr == 0) sd_card_read <= 1;
// we are busy until the right sector header passes under
// the head and the arm7 has delivered at least one byte
// (one byte is sufficient as the arm7 is much faster and
// all further bytes will arrive in time)
if(fd_ready && fd_sector_hdr &&
(fd_sector == sector) && (fifo_wptr != 0))
data_read_start_set <= 1'b1;
(fd_sector == sector) && (sd_buff_addr != 0))
data_transfer_start <= 1'b1;
if(data_read_done) begin
data_read_done_clr <= 1'b1;
if(data_transfer_done) begin
busy <= 1'b0;
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1;
irq_set <= 1'b1; // emit irq when command done
end
end
// write sector
if(cmd[7:5] == 3'b101) begin
if (fifo_cpuptr == 0) data_transfer_start <= 1'b1;
if (data_transfer_done) sd_card_write <= 1;
if (sd_card_write_done) begin
busy <= 1'b0;
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1;
irq_set <= 1'b1; // emit irq when command done
@@ -441,10 +468,9 @@ always @(posedge clkcpu) begin
if(cmd[7:4] == 4'b1100) begin
// we are busy until the next setor header passes under the head
if(fd_ready && fd_sector_hdr)
data_read_start_set <= 1'b1;
data_transfer_start <= 1'b1;
if(data_read_done) begin
data_read_done_clr <= 1'b1;
if(data_transfer_done) begin
busy <= 1'b0;
motor_timeout_index <= MOTOR_IDLE_COUNTER - 1;
irq_set <= 1'b1; // emit irq when command done
@@ -473,64 +499,127 @@ end
// floppy delivers data at a floppy generated rate (usually 250kbit/s), so the start and stop
// signals need to be passed forth and back from cpu clock domain to floppy data clock domain
reg data_read_start_set;
reg data_read_done_clr;
reg data_read_done;
reg data_transfer_start;
reg data_transfer_done;
// ==================================== FIFO ==================================
// 1 kB buffer used to receive a sector as fast as possible from from the io
// controller. The internal transfer afterwards then runs at 250000 Bit/s
reg [7:0] fifo [1023:0];
reg [10:0] fifo_rptr;
reg [10:0] fifo_wptr;
reg [10:0] fifo_cpuptr;
reg s_odd; //odd sector
wire [7:0] fifo_q;
// -------------------- data write -----------------------
always @(posedge clkcpu or posedge cmd_rx) begin
if(cmd_rx)
fifo_wptr <= 11'd0;
else begin
if(dio_in_strobe && (fifo_wptr != 11'd1024)) begin
fifo[fifo_wptr] <= dio_in;
fifo_wptr <= fifo_wptr + 11'd1;
end
end
end
// -------------------- data read -----------------------
fdc1772_dpram fifo
(
.clock(clkcpu),
.address_a({s_odd, sd_buff_addr}),
.data_a(sd_dout),
.wren_a(sd_dout_strobe & sd_ack),
.q_a(sd_din),
.address_b(fifo_cpuptr),
.data_b(data_in),
.wren_b(data_in_strobe),
.q_b(fifo_q)
);
// ------------------ SD card control ------------------------
localparam SD_IDLE = 0;
localparam SD_READ = 1;
localparam SD_WRITE = 2;
reg [1:0] sd_state;
reg sd_card_write;
reg sd_card_read;
reg sd_card_write_done;
reg [10:0] data_read_cnt;
always @(posedge clkcpu) begin
reg data_read_start_setD;
reg sd_ackD;
sd_ackD <= sd_ack;
if (sd_ack) {sd_rd, sd_wr} <= 0;
if (clk8m_en) sd_card_write_done <= 0;
case (sd_state)
SD_IDLE:
begin
s_odd <= 0;
if (sd_card_read) begin
sd_rd <= ~{ floppy_drive[1], floppy_drive[0] };
sd_state <= SD_READ;
end
else if (sd_card_write) begin
sd_wr <= ~{ floppy_drive[1], floppy_drive[0] };
sd_state <= SD_WRITE;
end
end
SD_READ:
begin
if (sd_ackD & ~sd_ack) begin
if (s_odd) sd_state <= SD_IDLE;
else begin
s_odd <= 1;
sd_rd <= ~{ floppy_drive[1], floppy_drive[0] };
end
end
end
SD_WRITE:
begin
if (sd_ackD & ~sd_ack) begin
if (s_odd) begin
sd_state <= SD_IDLE;
sd_card_write_done <= 1;
end else begin
s_odd <= 1;
sd_wr <= ~{ floppy_drive[1], floppy_drive[0] };
end
end
end
default: ;
endcase
end
// -------------------- CPU data read/write -----------------------
always @(posedge clkcpu) begin
reg data_transfer_startD;
reg [10:0] data_transfer_cnt;
// reset fifo read pointer on reception of a new command
if(cmd_rx)
fifo_rptr <= 11'd0;
fifo_cpuptr <= 11'd0;
drq_set <= 1'b0;
if (data_read_done_clr) data_read_done <= 0;
data_read_start_setD <= data_read_start_set;
if (clk8m_en) data_transfer_done <= 0;
data_transfer_startD <= data_transfer_start;
// received request to read data
if(~data_read_start_setD & data_read_start_set) begin
if(~data_transfer_startD & data_transfer_start) begin
// read_address command has 6 data bytes
if(cmd[7:4] == 4'b1100)
data_read_cnt <= 11'd6+11'd1;
data_transfer_cnt <= 11'd6+11'd1;
// read sector has 1024 data bytes
if(cmd[7:5] == 3'b100)
data_read_cnt <= 11'd1024+11'd1;
// read/write sector has 1024 data bytes
if(cmd[7:6] == 2'b10)
data_transfer_cnt <= 11'd1024+11'd1;
end
// write sector data arrived from CPU
if(cmd[7:5] == 3'b101 && data_in_strobe) fifo_cpuptr <= fifo_cpuptr + 1'd1;
if(fd_dclk_en) begin
if(data_read_cnt != 0) begin
if(data_read_cnt != 1) begin
if(data_transfer_cnt != 0) begin
if(data_transfer_cnt != 1) begin
drq_set <= 1'b1;
// read_address
if(cmd[7:4] == 4'b1100) begin
case(data_read_cnt)
case(data_transfer_cnt)
7: data_out <= fd_track;
6: data_out <= { 7'b0000000, floppy_side };
5: data_out <= fd_sector;
@@ -542,17 +631,17 @@ always @(posedge clkcpu) begin
// read sector
if(cmd[7:5] == 3'b100) begin
if(fifo_rptr != 11'd1024) begin
data_out <= fifo[fifo_rptr];
fifo_rptr <= fifo_rptr + 11'd1;
if(fifo_cpuptr != 11'd1024) begin
data_out <= fifo_q;
fifo_cpuptr <= fifo_cpuptr + 11'd1;
end
end
end
// count down and stop after last byte
data_read_cnt <= data_read_cnt - 11'd1;
if(data_read_cnt == 1)
data_read_done <= 1'b1;
data_transfer_cnt <= data_transfer_cnt - 11'd1;
if(data_transfer_cnt == 1)
data_transfer_done <= 1'b1;
end
end
end
@@ -605,7 +694,8 @@ end
reg cmd_rx;
reg cmd_rx_i;
reg last_stb;
reg data_in_strobe;
always @(posedge clkcpu) begin
if(!floppy_reset) begin
// clear internal registers
@@ -617,7 +707,9 @@ always @(posedge clkcpu) begin
cmd_rx_i <= 1'b0;
cmd_rx <= 1'b0;
last_stb <= 1'b0;
data_in_strobe <= 0;
end else begin
data_in_strobe <= 0;
last_stb <= wb_stb;
// cmd_rx is delayed to make sure all signals (the cmd!) are stable when
@@ -667,7 +759,7 @@ always @(posedge clkcpu) begin
end
if(wb_dat_i[7:5] == 3'b101) begin // write sector
end
end
// ------------- TYPE III commands ------------
if(wb_dat_i[7:4] == 4'b1100) begin // read address
@@ -690,10 +782,49 @@ always @(posedge clkcpu) begin
if(wb_adr[3:2] == FDC_REG_SECTOR) // sector register
sector <= wb_dat_i;
if(wb_adr[3:2] == FDC_REG_DATA) // data register
if(wb_adr[3:2] == FDC_REG_DATA) begin // data register
data_in_strobe <= 1;
data_in <= wb_dat_i;
end
end
end
end
endmodule
module fdc1772_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=10)
(
input clock,
input [ADDRWIDTH-1:0] address_a,
input [DATAWIDTH-1:0] data_a,
input wren_a,
output reg [DATAWIDTH-1:0] q_a,
input [ADDRWIDTH-1:0] address_b,
input [DATAWIDTH-1:0] data_b,
input wren_b,
output reg [DATAWIDTH-1:0] q_b
);
reg [DATAWIDTH-1:0] ram[0:(1<<ADDRWIDTH)-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] <= data_b;
q_b <= data_b;
end else begin
q_b <= ram[address_b];
end
end
endmodule