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:
@@ -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 ),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user