📄 floppy.v
字号:
// Copyright 2006, 2007 Dennis van Weeren//// This file is part of Minimig//// Minimig is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 3 of the License, or// (at your option) any later version.//// Minimig is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see <http://www.gnu.org/licenses/>.//////// This is the floppy disk controller (part of Paula)//// 23-10-2005 -started coding// 24-10-2005 -done lots of work// 13-11-2005 -modified fifo to use block ram// -done lots of work// 14-11-2005 -done more work// 19-11-2005 -added wordsync logic// 20-11-2005 -finished core floppy disk interface// -added disk interrupts// -added floppy control signal emulation// 21-11-2005 -cleaned up code a bit// 27-11-2005 -den and sden are now active low (_den and _sden)// -fixed bug in parallel/serial converter// -fixed more bugs// 02-12-2005 -removed dma abort function// 04-12-2005 -fixed bug in fifo empty signalling// 09-12-2005 -fixed dsksync handling // -added protection against stepping beyond track limits// 10-12-2005 -fixed some more bugs// 11-12-2005 -added dout output enable to allow SPI bus multiplexing// 12-12-2005 -fixed major bug, due error in statemachine, multiple interrupts were requested// after a DMA transfer, this could lock up the whole machine// -enable line disconnected --> this module still needs a lot of work// 27-12-2005 -cleaned up code, this is it for now// 07-01-2005 -added dmas// 15-01-2006 -added support for track 80-127 (used for loading kickstart)// 22-01-2006 -removed support for track 80-127 again// 06-02-2006 -added user disk control input// 28-12-2006 -spi data out is now low when not addressed to allow multiplexing with multiple spi devices // JB:// 2008-07-17 - modified floppy interface for better read handling and write support
// - spi interface clocked by SPI clockmodule floppy(
//bus interface input clk, //bus clock input reset, //reset input enable, //dma enable input [8:0]horbeam, //horizontal beamcounter input [8:1] regaddress, //register address inputs input [15:0]datain, //bus data in output [15:0]dataout, //bus data out output reg dmal, //dma request output output reg dmas, //dma special output //disk control signals from cia and user input [2:0]user, //user disk control input _step, //step heads of disk input direc, //step heads direction input _sel, //disk select input side, //upper/lower disk head input _motor, //disk motor control output _track0, //track zero detect output _change, //disk has been removed from drive output _ready, //disk is ready output _wprot, //disk is write-protected //interrupt request and misc. control output reg blckint, //disk dma has finished interrupt output syncint, //disk syncword found input wordsync, //wordsync enable //flash drive host controller interface (SPI) input _den, //async. serial data enable input din, //async. serial data input output dout, //async. serial data output input dclk //async. serial data clock);//register names and addresses parameter DSKBYTR=9'h01a; parameter DSKDAT =9'h026; parameter DSKDATR=9'h008; parameter DSKSYNC=9'h07e; parameter DSKLEN =9'h024; //local signals reg [15:0]dsksync; //disk sync register reg [15:0]dsklen; //disk dma length, direction and enable reg [7:0]track; //track select reg dmaon; //disk dma read/write enabled wire lenzero; //disk length counter is zero wire spidat; //data word read/written by external host reg trackwr; //write track (command to host) reg trackrd; //read track (command to host) reg trackch; //check track (command to host) reg _dskwprot; //disk is write protected reg _dskchange; //disk has been removed reg _dskready; //disk is ready (motor running) wire _dsktrack0; //disk heads are over track 0 wire [15:0]bufdin; //fifo data in wire [15:0]bufdout; //fifo data out wire bufwr; //fifo write enable reg bufwr_del; //fifo write enable delayed wire bufrd; //fifo read enable wire bufempty; //fifo is empty wire buffull; //fifo is full wire [15:0]dskbytr; wire [15:0]dskdatr; //JB: wire fifo_reset; reg dmaen; //dsklen dma enable wire [13:0]fifo_cnt; reg [15:0]wr_fifo_status;//-----------------------------------------------------------------------------------------------////JB: SPI interface//-----------------------------------------------------------------------------------------------//wire sck; //SPI clockwire scs; //SPI chip selectwire sdi; //SPI data inwire sdo; //SPI data outreg [3:0]spi_bit_cnt; //received bit counter - incremented on rising edge of SCKwire spi_bit_15;reg [15:1]spi_sdi_reg; //spi receive registerreg [15:0]rx_data; //spi received datareg [15:0]spi_sdo_reg; //spi transmit register (shifted on SCK falling edge)reg spi_rx_flag;reg rx_flag_sync;reg rx_flag;wire spi_rx_flag_clr;reg spi_tx_flag;reg tx_flag_sync;reg tx_flag;wire spi_tx_flag_clr;reg [15:0]spi_tx_data; //data to be send via SPIreg [1:0]tx_word_cnt; //transmitted word countreg spi_cmd0; // first command wordreg spi_cmd1; // first command wordreg spi_cmd2; // second command wordreg spi_dat; // data word//SPI mode 0 - high idle clockassign sck = dclk;assign sdi = din;assign scs = ~_den;assign dout = sdo;//received bits counter (0-15)always @(posedge sck or negedge scs) if (~scs) spi_bit_cnt <= 0; //reset if inactive chip select else spi_bit_cnt <= spi_bit_cnt + 1; assign spi_bit_15 = spi_bit_cnt==15 ? 1 : 0;//SDI input shift registeralways @(posedge sck) spi_sdi_reg <= {spi_sdi_reg[14:1],sdi}; //spi rx data registeralways @(posedge sck) if (spi_bit_15) rx_data <= {spi_sdi_reg[15:1],sdi}; // rx_flag is synchronous with clk and is set after receiving the last bit of a wordassign spi_rx_flag_clr = rx_flag | reset;always @(posedge sck or posedge spi_rx_flag_clr) if (spi_rx_flag_clr) spi_rx_flag <= 0; else if (spi_bit_cnt==15) spi_rx_flag <= 1;always @(negedge clk) rx_flag_sync <= spi_rx_flag; //double synchronization to avoid metastabilityalways @(posedge clk) rx_flag <= rx_flag_sync; //synchronous with clk// tx_flag is synchronous with clk and is set after sending the first bit of a wordassign spi_tx_flag_clr = tx_flag | reset;always @(negedge sck or posedge spi_tx_flag_clr) if (spi_tx_flag_clr) spi_tx_flag <= 0; else if (spi_bit_cnt==0) spi_tx_flag <= 1;always @(negedge clk) tx_flag_sync <= spi_tx_flag; //double synchronization to avoid metastabilityalways @(posedge clk) tx_flag <= tx_flag_sync; //synchronous with clk//---------------------------------------------------------------------------------------------------------------------always @(negedge sck or negedge scs) if (~scs) tx_word_cnt <= 0; else if (spi_bit_cnt==0 && tx_word_cnt!=2) tx_word_cnt <= tx_word_cnt + 1;always @(posedge sck or negedge scs) if (~scs) spi_cmd0 <= 1; else if (spi_bit_15) begin spi_cmd0 <= 0; spi_cmd1 <= spi_cmd0; spi_cmd2 <= ~spi_cmd0 & spi_cmd1; spi_dat <= ~spi_cmd0 & (spi_cmd2 | spi_dat); end//spidat strobe assign spidat = rx_flag & spi_dat;//------------------------------------//SDO output shift registeralways @(negedge sck) if (spi_bit_cnt==0) spi_sdo_reg <= spi_tx_data; else spi_sdo_reg <= {spi_sdo_reg[14:0],1'b0};assign sdo = scs & spi_sdo_reg[15];always @(spi_cmd0 or spi_cmd1 or user or trackch or trackrd or trackwr or track or dmaen or dsklen or bufdout or tx_word_cnt or wr_fifo_status)begin if (tx_word_cnt==0) spi_tx_data = {user[2:0],2'b00,trackch,trackrd,trackwr,track[7:0]}; else if (trackrd) spi_tx_data = {dmaen,dsklen[14:0]}; else if (trackwr) if (tx_word_cnt==1) spi_tx_data = wr_fifo_status; else spi_tx_data = bufdout; else spi_tx_data = 0;endalways @(posedge clk) if (tx_flag) wr_fifo_status <= {dmaen&dsklen[14],1'b0,fifo_cnt[13:0]};//-----------------------------------------------------------------------------------------------////-----------------------------------------------------------------------------------------------////--------------------------------------------------------------------------------------//data out multiplexerassign dataout = dskbytr | dskdatr;//--------------------------------------------------------------------------------------//floppy control signal behaviourreg _stepd; //used to detect rising edge of _stepreg _seld; //used to detect falling edge of _selwire _dsktrack79; //last track//_ready,_track0 and _change signalsassign {_track0,_change,_ready,_wprot}=(!_sel)?{_dsktrack0,_dskchange,_dskready,_dskwprot}:4'b1111; //delay _step and _selalways @(posedge clk)begin _stepd<=_step; _seld<=_sel;end//track controlalways @(posedge clk) track[0]<=~side;always @(posedge clk) if(reset)//reset track[7:1]<=0; else if((!_dsktrack79 && !direc) || (!_dsktrack0 && direc))//do not step beyond track limits track[7:1]<=track[7:1]; else if(!_sel && _step && !_stepd)//track increment (direc=0) or decrement (direc=1) at rising edge of _step
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -