From 860a597248042bc22d0481624d749d1c8a6b3997 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Fri, 1 Mar 2019 22:24:46 +0100 Subject: [PATCH] [Archie] Use standard IO for FDC with full read/write support Needs firmware update --- cores/archie/fpga/mist/archimedes_mist_top.v | 67 ++-- cores/archie/fpga/mist/data_io.v | 40 +-- cores/archie/fpga/mist/user_io.v | 133 +++++++- cores/archie/rtl/archimedes_top.v | 40 ++- cores/archie/rtl/fdc1772.v | 307 +++++++++++++------ 5 files changed, 425 insertions(+), 162 deletions(-) diff --git a/cores/archie/fpga/mist/archimedes_mist_top.v b/cores/archie/fpga/mist/archimedes_mist_top.v index 8cf262b..a23c821 100644 --- a/cores/archie/fpga/mist/archimedes_mist_top.v +++ b/cores/archie/fpga/mist/archimedes_mist_top.v @@ -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 ), diff --git a/cores/archie/fpga/mist/data_io.v b/cores/archie/fpga/mist/data_io.v index 2ab8aec..bdcc759 100644 --- a/cores/archie/fpga/mist/data_io.v +++ b/cores/archie/fpga/mist/data_io.v @@ -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 diff --git a/cores/archie/fpga/mist/user_io.v b/cores/archie/fpga/mist/user_io.v index e7f6c32..9b2bc34 100644 --- a/cores/archie/fpga/mist/user_io.v +++ b/cores/archie/fpga/mist/user_io.v @@ -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 diff --git a/cores/archie/rtl/archimedes_top.v b/cores/archie/rtl/archimedes_top.v index b56f55b..20e215b 100644 --- a/cores/archie/rtl/archimedes_top.v +++ b/cores/archie/rtl/archimedes_top.v @@ -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 ) ); diff --git a/cores/archie/rtl/fdc1772.v b/cores/archie/rtl/fdc1772.v index 03b8add..16c2ce6 100644 --- a/cores/archie/rtl/fdc1772.v +++ b/cores/archie/rtl/fdc1772.v @@ -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<