Revision 229
Added by markw almost 11 years ago
mist_5200/sd_card.v | ||
---|---|---|
//
|
||
// sd_card.v
|
||
//
|
||
// This file implelents a sd card for the MIST board since on the board
|
||
// the SD card is connected to the ARM IO controller and the FPGA has no
|
||
// direct connection to the SD card. This file provides a SD card like
|
||
// interface to the IO controller easing porting of cores that expect
|
||
// a direct interface to the SD card.
|
||
//
|
||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||
//
|
||
// This source file is free software: you can redistribute it and/or modify
|
||
// it under the terms of the Lesser GNU General Public License as published
|
||
// by the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// This source file 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/>.
|
||
//
|
||
// http://elm-chan.org/docs/mmc/mmc_e.html
|
||
|
||
// TODO:
|
||
// - CMD9: SEND_CSD (requires device capacity)
|
||
// - CMD10: SEND_CID
|
||
|
||
module sd_card (
|
||
// link to user_io for io controller
|
||
output [31:0] io_lba,
|
||
output reg io_rd,
|
||
output reg io_wr,
|
||
input io_ack,
|
||
output io_conf,
|
||
output io_sdhc,
|
||
|
||
// data coming in from io controller
|
||
input [7:0] io_din,
|
||
input io_din_strobe,
|
||
|
||
// data going out to io controller
|
||
output [7:0] io_dout,
|
||
input io_dout_strobe,
|
||
|
||
// configuration input
|
||
input allow_sdhc,
|
||
|
||
input sd_cs,
|
||
input sd_sck,
|
||
input sd_sdi,
|
||
output reg sd_sdo
|
||
);
|
||
|
||
// set io_rd once read_state machine starts waiting (rising edge of req_io_rd)
|
||
// and clear it once io controller uploads something (io_ack==1)
|
||
wire req_io_rd = (read_state == RD_STATE_WAIT_IO);
|
||
always @(posedge req_io_rd or posedge io_ack) begin
|
||
if(io_ack) io_rd <= 1'b0;
|
||
else io_rd <= 1'b1;
|
||
end
|
||
|
||
wire req_io_wr = (write_state == WR_STATE_BUSY);
|
||
always @(posedge req_io_wr or posedge io_ack) begin
|
||
if(io_ack) io_wr <= 1'b0;
|
||
else io_wr <= 1'b1;
|
||
end
|
||
|
||
wire [31:0] OCR = { 1'b0, io_sdhc, 30'h0 }; // bit30 = 1 -> high capaciry card (sdhc)
|
||
wire [7:0] READ_DATA_TOKEN = 8'hfe;
|
||
|
||
localparam NCR=4;
|
||
|
||
// 0=idle, 1=wait for io ctrl, 2=wait for byte start, 3=send token, 4=send data, 5/6=send crc[0..1]
|
||
localparam RD_STATE_IDLE = 3'd0;
|
||
localparam RD_STATE_WAIT_IO = 3'd1;
|
||
localparam RD_STATE_WAIT_START = 3'd2;
|
||
localparam RD_STATE_SEND_TOKEN = 3'd3;
|
||
localparam RD_STATE_SEND_DATA = 3'd4;
|
||
localparam RD_STATE_SEND_CRC0 = 3'd5;
|
||
localparam RD_STATE_SEND_CRC1 = 3'd6;
|
||
reg [2:0] read_state = RD_STATE_IDLE;
|
||
|
||
// 0=idle
|
||
localparam WR_STATE_IDLE = 3'd0;
|
||
localparam WR_STATE_EXP_DTOKEN = 3'd1;
|
||
localparam WR_STATE_RECV_DATA = 3'd2;
|
||
localparam WR_STATE_RECV_CRC0 = 3'd3;
|
||
localparam WR_STATE_RECV_CRC1 = 3'd4;
|
||
localparam WR_STATE_SEND_DRESP = 3'd5;
|
||
localparam WR_STATE_BUSY = 3'd6;
|
||
reg [2:0] write_state = WR_STATE_IDLE;
|
||
|
||
reg [6:0] sbuf;
|
||
reg cmd55;
|
||
reg new_cmd_rcvd;
|
||
reg [7:0] cmd;
|
||
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||
reg [3:0] byte_cnt= 4'd15; // counts bytes
|
||
|
||
reg [31:0] lba;
|
||
assign io_lba = io_sdhc?lba:{9'd0, lba[31:9]};
|
||
|
||
// the command crc is actually never evaluated
|
||
reg [7:0] crc;
|
||
|
||
reg [7:0] reply;
|
||
reg [7:0] reply0, reply1, reply2, reply3;
|
||
reg [3:0] reply_len;
|
||
|
||
// signals to address buffer on SD card write (data coming from SD spi)
|
||
reg write_strobe;
|
||
reg [7:0] write_data;
|
||
|
||
// falling edge of io_ack signals that a sector to be read has been written into
|
||
// the sector bufffer by the io controller. This signal is kept set as long
|
||
// as the read state machine is in the "wait for io controller" state (state 1)
|
||
wire rd_wait_io = (read_state == RD_STATE_WAIT_IO);
|
||
reg rd_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge rd_wait_io) begin
|
||
if(!rd_wait_io) rd_io_ack <= 1'b0;
|
||
else rd_io_ack <= 1'b1;
|
||
end
|
||
|
||
wire wr_wait_io = (write_state == WR_STATE_BUSY);
|
||
reg wr_io_ack = 1'b0 /* synthesis noprune */;
|
||
always @(negedge io_ack or negedge wr_wait_io) begin
|
||
if(!wr_wait_io) wr_io_ack <= 1'b0;
|
||
else wr_io_ack <= 1'b1;
|
||
end
|
||
|
||
// ------------------------- SECTOR BUFFER -----------------------
|
||
|
||
// access to the sector buffer is multiplexed. When reading sectors
|
||
// the io controller writes into the buffer and the sd card implementation
|
||
// reads. And vice versa when writing sectors
|
||
wire reading = (read_state != RD_STATE_IDLE);
|
||
wire writing = (write_state != WR_STATE_IDLE);
|
||
|
||
// the buffer itself. Can hold one sector
|
||
reg [8:0] buffer_wptr;
|
||
reg [8:0] buffer_rptr;
|
||
reg [7:0] buffer [511:0];
|
||
reg [7:0] buffer_byte;
|
||
|
||
// ---------------- buffer read engine -----------------------
|
||
reg core_buffer_read_strobe;
|
||
wire buffer_read_latch = reading?sd_sck:io_dout_strobe;
|
||
wire buffer_read_strobe = reading?core_buffer_read_strobe:!io_dout_strobe;
|
||
assign io_dout = buffer_byte;
|
||
|
||
// sdo is sampled on negative sd clock so set it on positive edge
|
||
always @(posedge buffer_read_latch)
|
||
buffer_byte <= buffer[buffer_rptr];
|
||
|
||
always @(posedge buffer_read_strobe or posedge new_cmd_rcvd) begin
|
||
if(new_cmd_rcvd == 1) buffer_rptr <= 9'd0;
|
||
else buffer_rptr <= buffer_rptr + 9'd1;
|
||
end
|
||
|
||
// ---------------- buffer write engine -----------------------
|
||
wire [7:0] buffer_din = reading?io_din:write_data;
|
||
wire buffer_din_strobe = reading?io_din_strobe:write_strobe;
|
||
|
||
always @(negedge buffer_din_strobe or posedge new_cmd_rcvd) begin
|
||
if(new_cmd_rcvd == 1) begin
|
||
buffer_wptr <= 9'd0;
|
||
end else begin
|
||
buffer[buffer_wptr] <= buffer_din;
|
||
buffer_wptr <= buffer_wptr + 9'd1;
|
||
end
|
||
end
|
||
|
||
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;
|
||
|
||
// ------------------------- CSD/CID BUFFER ----------------------
|
||
assign io_conf = (csd_wptr == 0); // csd_wptr still 0 -> configuration required
|
||
|
||
// the 32 bytes as sent from the io controller
|
||
reg [7:0] cid [15:0];
|
||
reg [7:0] csd [15:0];
|
||
reg [7:0] conf;
|
||
|
||
reg [7:0] cid_byte;
|
||
reg [7:0] csd_byte;
|
||
reg [5:0] csd_wptr = 6'd0;
|
||
|
||
// conf[0]==1 -> io controller is using an sdhc card
|
||
wire io_has_sdhc = conf[0];
|
||
assign io_sdhc = allow_sdhc && io_has_sdhc;
|
||
|
||
always @(negedge io_din_strobe) begin
|
||
// if io controller sends data without asserting io_ack, then it's
|
||
// updating the config
|
||
if(!io_ack && (csd_wptr <= 32)) begin
|
||
|
||
if(csd_wptr < 16) // first 16 bytes are cid
|
||
cid[csd_wptr] <= io_din;
|
||
if((csd_wptr >= 16) && (csd_wptr < 32)) // then comes csd
|
||
csd[csd_wptr-16] <= io_din;
|
||
if(csd_wptr == 32) // finally a config byte
|
||
conf <= io_din;
|
||
|
||
csd_wptr <= csd_wptr + 1;
|
||
end
|
||
end
|
||
|
||
always @(posedge buffer_read_latch)
|
||
cid_byte <= cid[buffer_rptr];
|
||
|
||
always @(posedge buffer_read_latch)
|
||
csd_byte <= csd[buffer_rptr];
|
||
|
||
// ----------------- spi transmitter --------------------
|
||
reg rd_io_ackD, wr_io_ackD;
|
||
|
||
always@(negedge sd_sck or posedge sd_cs) begin
|
||
if(sd_cs == 1) begin
|
||
// sd_sdo <= 1'b1;
|
||
// read_state <= RD_STATE_IDLE;
|
||
end else begin
|
||
core_buffer_read_strobe <= 1'b0;
|
||
|
||
// using rd_io_ack directly brings the read state machine into an
|
||
// non-existing state every now and then. For unknown reason
|
||
rd_io_ackD <= rd_io_ack;
|
||
|
||
// -------- catch read commmand and reset read state machine ------
|
||
if(bit_cnt == 7) begin
|
||
if(byte_cnt == 4) begin
|
||
// CMD17: READ_SINGLE_BLOCK
|
||
if(cmd == 8'h51)
|
||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||
end
|
||
end
|
||
|
||
if(byte_cnt < 5+NCR) begin
|
||
sd_sdo <= 1'b1; // reply $ff -> wait
|
||
end else begin
|
||
|
||
if(byte_cnt == 5+NCR) begin
|
||
sd_sdo <= reply[~bit_cnt];
|
||
|
||
if(bit_cnt == 7) begin
|
||
// CMD9: SEND_CSD
|
||
// CMD10: SEND_CID
|
||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||
end
|
||
end
|
||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||
sd_sdo <= reply0[~bit_cnt];
|
||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2))
|
||
sd_sdo <= reply1[~bit_cnt];
|
||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3))
|
||
sd_sdo <= reply2[~bit_cnt];
|
||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4))
|
||
sd_sdo <= reply3[~bit_cnt];
|
||
else
|
||
sd_sdo <= 1'b1;
|
||
|
||
// falling edge of io_ack signals end of incoming data stream
|
||
if((read_state == RD_STATE_WAIT_IO) && rd_io_ackD)
|
||
read_state <= RD_STATE_WAIT_START;
|
||
|
||
// wait for begin of new byte
|
||
else if((read_state == RD_STATE_WAIT_START) && (bit_cnt == 7))
|
||
read_state <= RD_STATE_SEND_TOKEN;
|
||
|
||
// send data token
|
||
else if(read_state == RD_STATE_SEND_TOKEN) begin
|
||
sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
|
||
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||
end
|
||
|
||
// send data
|
||
else if(read_state == RD_STATE_SEND_DATA) begin
|
||
if(cmd == 8'h51) // CMD17: READ_SINGLE_BLOCK
|
||
sd_sdo <= buffer_byte[~bit_cnt];
|
||
else if(cmd == 8'h49) // CMD9: SEND_CSD
|
||
sd_sdo <= csd_byte[~bit_cnt];
|
||
else if(cmd == 8'h4a) // CMD10: SEND_CID
|
||
sd_sdo <= cid_byte[~bit_cnt];
|
||
|
||
if(bit_cnt == 7) begin
|
||
core_buffer_read_strobe <= 1'b1;
|
||
|
||
// send 512 sector data bytes?
|
||
if((cmd == 8'h51) && (buffer_rptr == 511))
|
||
read_state <= RD_STATE_SEND_CRC0; // next: send crc
|
||
|
||
// send 16 cid/csd data bytes?
|
||
if(((cmd == 8'h49)||(cmd == 8'h4a)) && (buffer_rptr == 15))
|
||
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
end
|
||
|
||
// send crc[0]
|
||
else if(read_state == RD_STATE_SEND_CRC0) begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_SEND_CRC1; // send second crc byte
|
||
end
|
||
|
||
// send crc[1]
|
||
else if(read_state == RD_STATE_SEND_CRC1) begin
|
||
sd_sdo <= 1'b1;
|
||
if(bit_cnt == 7)
|
||
read_state <= RD_STATE_IDLE; // return to idle state
|
||
end
|
||
|
||
// ------------------ write support ----------------------
|
||
// send write data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||
|
||
// busy after write until the io controller sends ack
|
||
if(write_state == WR_STATE_BUSY)
|
||
sd_sdo <= 1'b0;
|
||
end
|
||
end
|
||
end
|
||
|
||
// spi receiver
|
||
always @(posedge sd_sck or posedge sd_cs) begin
|
||
// cs is active low
|
||
if(sd_cs == 1) begin
|
||
bit_cnt <= 3'd0;
|
||
// byte_cnt <= 4'd15;
|
||
// write_state <= WR_STATE_IDLE;
|
||
// write_strobe <= 1'b0;
|
||
end else begin
|
||
new_cmd_rcvd <= 1'b0;
|
||
write_strobe <= 1'b0;
|
||
sbuf[6:0] <= { sbuf[5:0], sd_sdi };
|
||
bit_cnt <= bit_cnt + 3'd1;
|
||
|
||
// using wr_io_ack directly brings the write state machine into an
|
||
// non-existing state every now and then. For unknown reason
|
||
wr_io_ackD <= wr_io_ack;
|
||
|
||
// finished reading command byte
|
||
if(bit_cnt == 7) begin
|
||
// byte counter runs against 15 byte boundary
|
||
if(byte_cnt != 15)
|
||
byte_cnt <= byte_cnt + 8'd1;
|
||
|
||
// byte_cnt > 6 -> complete command received
|
||
// first byte of valid command is 01xxxxxx
|
||
if((byte_cnt > 5) && (write_state == WR_STATE_IDLE) && sbuf[6:5] == 2'b01)
|
||
byte_cnt <= 4'd0;
|
||
|
||
// don't accept new commands once a write command has been accepted
|
||
if((write_state == WR_STATE_IDLE) && (byte_cnt > 5)&&(sbuf[6:5] == 2'b01)) begin
|
||
cmd <= { sbuf, sd_sdi};
|
||
new_cmd_rcvd <= 1'b1;
|
||
|
||
// set cmd55 flag if previous command was 55
|
||
cmd55 <= (cmd == 8'h77);
|
||
end
|
||
|
||
// parse additional command bytes
|
||
if(byte_cnt == 0) lba[31:24] <= { sbuf, sd_sdi};
|
||
if(byte_cnt == 1) lba[23:16] <= { sbuf, sd_sdi};
|
||
if(byte_cnt == 2) lba[15:8] <= { sbuf, sd_sdi};
|
||
if(byte_cnt == 3) lba[7:0] <= { sbuf, sd_sdi};
|
||
|
||
// last byte received, evaluate
|
||
if(byte_cnt == 4) begin
|
||
// crc is currently unused
|
||
crc <= { sbuf, sd_sdi};
|
||
|
||
// default:
|
||
reply <= 8'h04; // illegal command
|
||
reply_len <= 4'd0; // no extra reply bytes
|
||
|
||
// CMD0: GO_IDLE_STATE
|
||
if(cmd == 8'h40)
|
||
reply <= 8'h01; // ok, busy
|
||
|
||
// CMD1: SEND_OP_COND
|
||
else if(cmd == 8'h41)
|
||
reply <= 8'h00; // ok, not busy
|
||
|
||
// CMD8: SEND_IF_COND (V2 only)
|
||
else if(cmd == 8'h48) begin
|
||
reply <= 8'h01; // ok, busy
|
||
reply0 <= 8'h00;
|
||
reply1 <= 8'h00;
|
||
reply2 <= 8'h01;
|
||
reply3 <= 8'hAA;
|
||
reply_len <= 4'd4;
|
||
end
|
||
|
||
// CMD9: SEND_CSD
|
||
else if(cmd == 8'h49)
|
||
reply <= 8'h00; // ok
|
||
|
||
// CMD10: SEND_CID
|
||
else if(cmd == 8'h4a)
|
||
reply <= 8'h00; // ok
|
||
|
||
// CMD16: SET_BLOCKLEN
|
||
else if(cmd == 8'h50) begin
|
||
// we only support a block size of 512
|
||
if(io_lba == 32'd512)
|
||
reply <= 8'h00; // ok
|
||
else
|
||
reply <= 8'h40; // parmeter error
|
||
end
|
||
|
||
// CMD17: READ_SINGLE_BLOCK
|
||
else if(cmd == 8'h51)
|
||
reply <= 8'h00; // ok
|
||
|
||
// CMD24: WRITE_BLOCK
|
||
else if(cmd == 8'h58) begin
|
||
reply <= 8'h00; // ok
|
||
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
|
||
end
|
||
|
||
// ACMD41: APP_SEND_OP_COND
|
||
else if(cmd55 && (cmd == 8'h69))
|
||
reply <= 8'h00; // ok, not busy
|
||
|
||
// CMD55: APP_COND
|
||
else if(cmd == 8'h77)
|
||
reply <= 8'h01; // ok, busy
|
||
|
||
// CMD58: READ_OCR
|
||
else if(cmd == 8'h7a) begin
|
||
reply <= 8'h00; // ok
|
||
|
||
reply0 <= OCR[31:24]; // bit 30 = 1 -> high capacity card
|
||
reply1 <= OCR[23:16];
|
||
reply2 <= OCR[15:8];
|
||
reply3 <= OCR[7:0];
|
||
reply_len <= 4'd4;
|
||
end
|
||
end
|
||
|
||
// ---------- handle write -----------
|
||
|
||
// waiting for data token
|
||
if(write_state == WR_STATE_EXP_DTOKEN) begin
|
||
if({ sbuf, sd_sdi} == 8'hfe )
|
||
write_state <= WR_STATE_RECV_DATA;
|
||
end
|
||
|
||
// transfer 512 bytes
|
||
if(write_state == WR_STATE_RECV_DATA) begin
|
||
// push one byte into local buffer
|
||
write_strobe <= 1'b1;
|
||
write_data <= { sbuf, sd_sdi};
|
||
|
||
if(buffer_wptr == 511)
|
||
write_state <= WR_STATE_RECV_CRC0;
|
||
end
|
||
|
||
// transfer 1st crc byte
|
||
if(write_state == WR_STATE_RECV_CRC0)
|
||
write_state <= WR_STATE_RECV_CRC1;
|
||
|
||
// transfer 2nd crc byte
|
||
if(write_state == WR_STATE_RECV_CRC1)
|
||
write_state <= WR_STATE_SEND_DRESP;
|
||
|
||
// send data response
|
||
if(write_state == WR_STATE_SEND_DRESP)
|
||
write_state <= WR_STATE_BUSY;
|
||
end
|
||
|
||
// wait for io controller to accept data
|
||
// this happens outside the bit_cnt == 7 test as the
|
||
// transition may happen at any time
|
||
if(write_state == WR_STATE_BUSY && wr_io_ackD)
|
||
write_state <= WR_STATE_IDLE;
|
||
end
|
||
end
|
||
|
||
endmodule
|
mist_5200/atari800core.qsf | ||
---|---|---|
|
||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||
|
||
set_global_assignment -name VHDL_FILE data_io.vhdl
|
||
set_global_assignment -name VHDL_FILE zpu_rom.vhdl
|
||
set_global_assignment -name SDC_FILE atari800core.sdc
|
||
set_global_assignment -name QIP_FILE mist_sector_buffer.qip
|
||
set_global_assignment -name VHDL_FILE atari800core_mist.vhd
|
||
set_global_assignment -name VERILOG_FILE sd_card.v
|
||
set_global_assignment -name VERILOG_FILE user_io.v
|
||
set_global_assignment -name QIP_FILE pll_pal_pre.qip
|
||
set_global_assignment -name QIP_FILE pll_pal_post.qip
|
mist_5200/atari800core_mist.vhd | ||
---|---|---|
);
|
||
end component;
|
||
|
||
component sd_card
|
||
PORT (
|
||
-- link to user_io for io controller
|
||
io_lba : out std_logic_vector(31 downto 0);
|
||
io_rd : out std_logic;
|
||
io_wr : out std_logic;
|
||
io_ack : in std_logic;
|
||
io_conf : out std_logic;
|
||
io_sdhc : out std_logic;
|
||
|
||
-- data coming in from io controller
|
||
io_din : in std_logic_vector(7 downto 0);
|
||
io_din_strobe : in std_logic;
|
||
|
||
-- data going out to io controller
|
||
io_dout : out std_logic_vector(7 downto 0);
|
||
io_dout_strobe : in std_logic;
|
||
|
||
-- configuration input
|
||
allow_sdhc : in std_logic;
|
||
|
||
sd_cs : in std_logic;
|
||
sd_sck : in std_logic;
|
||
sd_sdi : in std_logic;
|
||
sd_sdo : out std_logic
|
||
);
|
||
end component;
|
||
|
||
signal AUDIO_L_PCM : std_logic_vector(15 downto 0);
|
||
signal AUDIO_R_PCM : std_logic_vector(15 downto 0);
|
||
|
||
... | ... | |
|
||
SIGNAL PS2_CLK : std_logic;
|
||
SIGNAL PS2_DAT : std_logic;
|
||
SIGNAL CONSOL_OPTION_RAW : STD_LOGIC;
|
||
SIGNAL CONSOL_OPTION : STD_LOGIC;
|
||
SIGNAL CONSOL_SELECT_RAW : STD_LOGIC;
|
||
SIGNAL CONSOL_SELECT : STD_LOGIC;
|
||
SIGNAL CONSOL_START_RAW : STD_LOGIC;
|
||
SIGNAL CONSOL_START : STD_LOGIC;
|
||
SIGNAL FKEYS : std_logic_vector(11 downto 0);
|
||
|
||
signal capslock_pressed : std_logic;
|
||
signal capsheld_next : std_logic;
|
||
signal capsheld_reg : std_logic;
|
||
|
||
signal mist_sector_ready : std_logic;
|
||
signal mist_sector_ready_sync : std_logic;
|
||
signal mist_sector_request : std_logic;
|
||
signal mist_sector_request_sync : std_logic;
|
||
signal mist_sector_write : std_logic;
|
||
signal mist_sector_write_sync : std_logic;
|
||
signal mist_sector : std_logic_vector(25 downto 0);
|
||
signal mist_sector_sync : std_logic_vector(25 downto 0);
|
||
|
||
|
||
signal mist_addr : std_logic_vector(8 downto 0);
|
||
signal mist_do : std_logic_vector(7 downto 0);
|
||
signal mist_di : std_logic_vector(7 downto 0);
|
||
signal mist_wren : std_logic;
|
||
|
||
signal spi_miso_data : std_logic;
|
||
signal spi_miso_io : std_logic;
|
||
|
||
signal mist_buttons : std_logic_vector(1 downto 0);
|
||
... | ... | |
signal pause_atari : std_logic;
|
||
SIGNAL speed_6502 : std_logic_vector(5 downto 0);
|
||
|
||
-- connection to sd card emulation
|
||
signal sd_lba : std_logic_vector(31 downto 0);
|
||
signal sd_rd : std_logic;
|
||
signal sd_wr : std_logic;
|
||
signal sd_ack : std_logic;
|
||
signal sd_conf : std_logic;
|
||
signal sd_sdhc : std_logic;
|
||
signal sd_dout : std_logic_vector(7 downto 0);
|
||
signal sd_dout_strobe : std_logic;
|
||
signal sd_din : std_logic_vector(7 downto 0);
|
||
signal sd_din_strobe : std_logic;
|
||
-- mist sector
|
||
signal ZPU_ROM_DATA_MUX : std_logic_vector(31 downto 0);
|
||
signal ZPU_SECTOR_DATA : std_logic_vector(31 downto 0);
|
||
signal ZPU_ROM_DO : std_logic_vector(31 downto 0);
|
||
signal ZPU_ROM_WREN : std_logic;
|
||
|
||
signal mist_sd_sdo : std_logic;
|
||
signal mist_sd_sck : std_logic;
|
||
signal mist_sd_sdi : std_logic;
|
||
signal mist_sd_cs : std_logic;
|
||
|
||
-- ps2
|
||
signal SLOW_PS2_CLK : std_logic; -- around 16KHz
|
||
|
||
... | ... | |
composite_on_hsync <= '1' when composite_sync=1 else '0';
|
||
|
||
-- mist spi io
|
||
spi_do <= spi_miso_io when CONF_DATA0 ='0' else 'Z';
|
||
mist_spi_interface : entity work.data_io
|
||
PORT map
|
||
(
|
||
CLK =>spi_sck,
|
||
RESET_n =>reset_n,
|
||
|
||
-- SPI connection - up to upstream to make miso 'Z' on ss_io going high
|
||
SPI_CLK =>spi_sck,
|
||
SPI_SS_IO => spi_ss2,
|
||
SPI_MISO => spi_miso_data,
|
||
SPI_MOSI => spi_di,
|
||
|
||
-- Sector access request
|
||
read_request => mist_sector_request_sync,
|
||
write_request => mist_sector_write_sync,
|
||
--request => mist_sector_request_sync,
|
||
sector => mist_sector_sync(25 downto 0),
|
||
ready => mist_sector_ready,
|
||
|
||
-- DMA to RAM
|
||
ADDR => mist_addr,
|
||
DATA_OUT => mist_do,
|
||
DATA_IN => mist_di,
|
||
WR_EN => mist_wren
|
||
);
|
||
|
||
-- TODO, review if these are all needed when ZPU connected again...
|
||
select_sync : entity work.synchronizer
|
||
PORT MAP ( CLK => clk, raw => mist_sector_ready, sync=>mist_sector_ready_sync);
|
||
|
||
select_sync2 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector_request, sync=>mist_sector_request_sync);
|
||
|
||
select_sync3 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector_write, sync=>mist_sector_write_sync);
|
||
|
||
sector_sync0 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(0), sync=>mist_sector_sync(0));
|
||
|
||
sector_sync1 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(1), sync=>mist_sector_sync(1));
|
||
|
||
sector_sync2 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(2), sync=>mist_sector_sync(2));
|
||
|
||
sector_sync3 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(3), sync=>mist_sector_sync(3));
|
||
|
||
sector_sync4 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(4), sync=>mist_sector_sync(4));
|
||
|
||
sector_sync5 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(5), sync=>mist_sector_sync(5));
|
||
|
||
sector_sync6 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(6), sync=>mist_sector_sync(6));
|
||
|
||
sector_sync7 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(7), sync=>mist_sector_sync(7));
|
||
|
||
sector_sync8 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(8), sync=>mist_sector_sync(8));
|
||
|
||
sector_sync9 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(9), sync=>mist_sector_sync(9));
|
||
|
||
sector_sync10 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(10), sync=>mist_sector_sync(10));
|
||
|
||
sector_sync11 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(11), sync=>mist_sector_sync(11));
|
||
|
||
sector_sync12 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(12), sync=>mist_sector_sync(12));
|
||
|
||
sector_sync13 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(13), sync=>mist_sector_sync(13));
|
||
|
||
sector_sync14 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(14), sync=>mist_sector_sync(14));
|
||
|
||
sector_sync15 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(15), sync=>mist_sector_sync(15));
|
||
|
||
sector_sync16 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(16), sync=>mist_sector_sync(16));
|
||
|
||
sector_sync17 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(17), sync=>mist_sector_sync(17));
|
||
|
||
sector_sync18 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(18), sync=>mist_sector_sync(18));
|
||
|
||
sector_sync19 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(19), sync=>mist_sector_sync(19));
|
||
|
||
sector_sync20 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(20), sync=>mist_sector_sync(20));
|
||
|
||
sector_sync21 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(21), sync=>mist_sector_sync(21));
|
||
|
||
sector_sync22 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(22), sync=>mist_sector_sync(22));
|
||
|
||
sector_sync23 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(23), sync=>mist_sector_sync(23));
|
||
|
||
sector_sync24 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(24), sync=>mist_sector_sync(24));
|
||
|
||
sector_sync25 : entity work.synchronizer
|
||
PORT MAP ( CLK => spi_sck, raw => mist_sector(25), sync=>mist_sector_sync(25));
|
||
|
||
|
||
spi_do <= spi_miso_io when CONF_DATA0 ='0' else spi_miso_data when spi_SS2='0' else 'Z';
|
||
|
||
mist_sector_buffer1 : entity work.mist_sector_buffer
|
||
PORT map
|
||
(
|
||
address_a => mist_addr,
|
||
address_b => zpu_addr_rom(8 downto 2),
|
||
clock_a => spi_sck,
|
||
clock_b => clk,
|
||
data_a => mist_do,
|
||
data_b => dma_write_data(7 downto 0)&dma_write_data(15 downto 8)&dma_write_data(23 downto 16)&dma_write_data(31 downto 24),
|
||
wren_a => mist_wren,
|
||
wren_b => zpu_rom_wren,
|
||
q_a => mist_di,
|
||
q_b => zpu_sector_data
|
||
);
|
||
|
||
my_user_io : user_io
|
||
PORT map(
|
||
SPI_CLK => SPI_SCK,
|
||
... | ... | |
JOYSTICK_ANALOG_1(7 downto 0) => joy1y,
|
||
BUTTONS => mist_buttons,
|
||
SWITCHES => mist_switches,
|
||
STATUS => open,
|
||
|
||
PS2_CLK => SLOW_PS2_CLK,
|
||
PS2_KBD_CLK => ps2_clk,
|
||
PS2_KBD_DATA => ps2_dat,
|
||
|
||
STATUS => open,
|
||
SERIAL_DATA => (others=>'0'),
|
||
SERIAL_STROBE => '0',
|
||
|
||
sd_lba => sd_lba,
|
||
sd_rd => sd_rd,
|
||
sd_wr => sd_wr,
|
||
sd_ack => sd_ack,
|
||
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_lba => (others=>'0'),
|
||
sd_rd => '0',
|
||
sd_wr => '0',
|
||
sd_conf => '0',
|
||
sd_sdhc => '0',
|
||
sd_din => (others=>'0')
|
||
|
||
);
|
||
|
||
my_sd_card : sd_card
|
||
PORT map (
|
||
io_lba => sd_lba,
|
||
io_rd => sd_rd,
|
||
io_wr => sd_wr,
|
||
io_ack => sd_ack,
|
||
io_conf => sd_conf,
|
||
io_sdhc => sd_sdhc,
|
||
|
||
io_din => sd_dout,
|
||
io_din_strobe => sd_dout_strobe,
|
||
|
||
io_dout => sd_din,
|
||
io_dout_strobe => sd_din_strobe,
|
||
|
||
allow_sdhc => '1',
|
||
|
||
sd_cs => mist_sd_cs,
|
||
sd_sck => mist_sd_sck,
|
||
sd_sdi => mist_sd_sdi,
|
||
sd_sdo => mist_sd_sdo
|
||
);
|
||
|
||
joy1_n <= not(joy1(4 downto 0));
|
||
joy2_n <= not(joy2(4 downto 0));
|
||
joy1_n <= not(joy1(5)&joy1(3 downto 0));
|
||
joy2_n <= not(joy2(5)&joy2(3 downto 0));
|
||
|
||
-- PS2 to pokey
|
||
keyboard_map1 : entity work.ps2_to_atari5200
|
||
... | ... | |
PS2_CLK => ps2_clk,
|
||
PS2_DAT => ps2_dat,
|
||
|
||
FIRE2 => '0'&'0'&joy2(5)&joy1(5),
|
||
FIRE2 => '0'&'0'&joy2(4)&joy1(4),
|
||
CONTROLLER_SELECT => CONTROLLER_SELECT, -- selected stick keyboard/shift button
|
||
|
||
KEYBOARD_SCAN => KEYBOARD_SCAN,
|
||
... | ... | |
|
||
FKEYS => FKEYS
|
||
);
|
||
-- stick 0: consol(1 downto 0)="00"
|
||
--keyboard_map1 : entity work.ps2_to_atari800
|
||
-- PORT MAP
|
||
-- (
|
||
-- CLK => clk,
|
||
-- RESET_N => reset_n,
|
||
-- PS2_CLK => ps2_clk,
|
||
-- PS2_DAT => ps2_dat,
|
||
--
|
||
-- KEYBOARD_SCAN => KEYBOARD_SCAN,
|
||
-- KEYBOARD_RESPONSE => KEYBOARD_RESPONSE,
|
||
--
|
||
-- CONSOL_START => CONSOL_START_RAW,
|
||
-- CONSOL_SELECT => CONSOL_SELECT_RAW,
|
||
-- CONSOL_OPTION => CONSOL_OPTION_RAW,
|
||
--
|
||
-- FKEYS => FKEYS
|
||
-- );
|
||
|
||
joy_still <= joy1_n(3) and joy1_n(2) and joy1_n(1) and joy1_n(0); -- TODO, need something better here I think! e.g. keypad? 5200 not centreing
|
||
CONSOL_START <= CONSOL_START_RAW or (mist_buttons(1) and not(joy1_n(4)));
|
||
joy_still <= joy1_n(3) and joy1_n(2) and joy1_n(1) and joy1_n(0);
|
||
CONSOL_SELECT <= CONSOL_SELECT_RAW or (mist_buttons(1) and joy1_n(4) and not(joy_still));
|
||
CONSOL_OPTION <= CONSOL_OPTION_RAW or (mist_buttons(1) and joy1_n(4) and joy_still);
|
||
|
||
dac_left : hq_dac
|
||
port map
|
||
... | ... | |
-- JOYSTICK
|
||
JOY1_X => signed(joy1x),
|
||
JOY1_Y => signed(joy1y),
|
||
JOY1_BUTTON => joy1(4),
|
||
JOY1_BUTTON => joy1_n(4),
|
||
JOY2_X => signed(joy2x),
|
||
JOY2_Y => signed(joy2y),
|
||
JOY2_BUTTON => joy2(4),
|
||
JOY2_BUTTON => joy2_n(4),
|
||
|
||
-- Pokey keyboard matrix
|
||
-- Standard component available to connect this to PS2
|
||
... | ... | |
GENERIC MAP
|
||
(
|
||
platform => 1,
|
||
spi_clock_div => 16 -- 28MHz/2. Max for SD cards is 25MHz...
|
||
spi_clock_div => 1 -- 28MHz/2. Max for SD cards is 25MHz...
|
||
)
|
||
PORT MAP
|
||
(
|
||
... | ... | |
-- rom bus master
|
||
-- data on next cycle after addr
|
||
ZPU_ADDR_ROM => zpu_addr_rom,
|
||
ZPU_ROM_DATA => zpu_rom_data,
|
||
ZPU_ROM_DATA => zpu_rom_data_mux,
|
||
|
||
ZPU_ROM_WREN => open,
|
||
ZPU_ROM_WREN => zpu_rom_wren, -- special for mist...
|
||
|
||
-- spi master
|
||
ZPU_SD_DAT0 => mist_sd_sdo,
|
||
ZPU_SD_CLK => mist_sd_sck,
|
||
ZPU_SD_CMD => mist_sd_sdi,
|
||
ZPU_SD_DAT3 => mist_sd_cs,
|
||
-- not used for mist...
|
||
ZPU_SD_DAT0 => '0',
|
||
ZPU_SD_CLK => open,
|
||
ZPU_SD_CMD => open,
|
||
ZPU_SD_DAT3 => open,
|
||
|
||
-- SIO
|
||
-- Ditto for speaking to Atari, we have a built in Pokey
|
||
... | ... | |
ZPU_IN1 => X"00000"&(FKEYS(11) or (mist_buttons(0) and not(joy1_n(4))))&(FKEYS(10) or (mist_buttons(0) and joy1_n(4) and joy_still))&(FKEYS(9) or (mist_buttons(0) and joy1_n(4) and not(joy_still)))&FKEYS(8 downto 0),
|
||
ZPU_IN2 => X"00000000",
|
||
ZPU_IN3 => X"00000000",
|
||
ZPU_IN4 => X"00000000",
|
||
ZPU_IN4 => X"000000"&"0000000"&mist_sector_ready_sync,
|
||
|
||
-- ouputs - e.g. Atari system control, halt, throttle, rom select
|
||
ZPU_OUT1 => zpu_out1,
|
||
... | ... | |
ZPU_OUT4 => zpu_out4
|
||
);
|
||
|
||
mist_sector <= zpu_out4(25 downto 0);
|
||
mist_sector_request <= zpu_out4(26);
|
||
mist_sector_write <= zpu_out4(27);
|
||
|
||
pause_atari <= zpu_out1(0);
|
||
reset_atari <= zpu_out1(1);
|
||
speed_6502 <= zpu_out1(7 downto 2);
|
||
... | ... | |
q => zpu_rom_data
|
||
);
|
||
|
||
process(zpu_addr_rom, zpu_rom_data, zpu_sector_data)
|
||
begin
|
||
zpu_rom_data_mux <= zpu_rom_data;
|
||
if (zpu_addr_rom(15 downto 14) = "01") then
|
||
zpu_rom_data_mux <= zpu_sector_data(7 downto 0)&zpu_sector_data(15 downto 8)&zpu_sector_data(23 downto 16)&zpu_sector_data(31 downto 24);
|
||
end if;
|
||
end process;
|
||
|
||
enable_179_clock_div_zpu_pokey : entity work.enable_divider
|
||
generic map (COUNT=>32) -- cycle_length
|
||
port map(clk=>clk,reset_n=>reset_n,enable_in=>'1',enable_out=>zpu_pokey_enable);
|
mist_5200/data_io.vhdl | ||
---|---|---|
LIBRARY ieee;
|
||
USE ieee.std_logic_1164.all;
|
||
use ieee.numeric_std.all;
|
||
|
||
LIBRARY work;
|
||
|
||
ENTITY data_io IS
|
||
PORT
|
||
(
|
||
CLK : in std_logic;
|
||
RESET_n : in std_logic;
|
||
|
||
-- SPI connection - up to upstream to make miso 'Z' on ss_io going high
|
||
SPI_CLK : in std_logic;
|
||
SPI_SS_IO : in std_logic;
|
||
SPI_MISO: out std_logic;
|
||
SPI_MOSI : in std_logic;
|
||
|
||
-- Sector access read_request
|
||
read_request : in std_logic;
|
||
write_request : in std_logic;
|
||
sector : in std_logic_vector(25 downto 0);
|
||
ready : out std_logic;
|
||
|
||
-- DMA to RAM
|
||
ADDR: out std_logic_vector(8 downto 0);
|
||
DATA_OUT : out std_logic_vector(7 downto 0);
|
||
DATA_IN : in std_logic_vector(7 downto 0);
|
||
WR_EN : out std_logic
|
||
);
|
||
end data_io;
|
||
|
||
architecture vhdl of data_io is
|
||
|
||
|
||
signal sbuf_next : std_logic_vector(6 downto 0);
|
||
signal sbuf_reg : std_logic_vector(6 downto 0);
|
||
|
||
signal cmd_next : std_logic_vector(7 downto 0);
|
||
signal cmd_reg : std_logic_vector(7 downto 0);
|
||
|
||
signal cnt_next : std_logic_vector(15 downto 0);
|
||
signal cnt_reg : std_logic_vector(15 downto 0);
|
||
|
||
signal data_in_next : std_logic_vector(7 downto 0);
|
||
signal data_in_reg : std_logic_vector(7 downto 0);
|
||
|
||
signal data_out_next : std_logic_vector(7 downto 0);
|
||
signal data_out_reg : std_logic_vector(7 downto 0);
|
||
|
||
signal addr_next : std_logic_vector(8 downto 0);
|
||
signal addr_reg : std_logic_vector(8 downto 0);
|
||
|
||
signal wren_next : std_logic;
|
||
signal wren_reg : std_logic;
|
||
|
||
signal ready_next : std_logic;
|
||
signal ready_reg : std_logic;
|
||
|
||
signal transmit_next : std_logic_vector(7 downto 0);
|
||
signal transmit_reg : std_logic_vector(7 downto 0);
|
||
|
||
signal sector_next : std_logic_vector(25 downto 0);
|
||
signal sector_reg : std_logic_vector(25 downto 0);
|
||
|
||
signal read_request_next : std_logic;
|
||
signal read_request_reg : std_logic;
|
||
|
||
signal write_request_next : std_logic;
|
||
signal write_request_reg : std_logic;
|
||
|
||
signal clk2 : std_logic;
|
||
begin
|
||
clk2 <= clk or spi_ss_io;
|
||
|
||
process(clk2,reset_n,spi_ss_io)
|
||
begin
|
||
if (spi_ss_io = '1') then
|
||
cnt_reg <= (others=>'0');
|
||
cmd_reg <= (others=>'0');
|
||
wren_reg <= '0';
|
||
elsif (reset_n = '0') then
|
||
cnt_reg <= (others=>'0');
|
||
cmd_reg <= (others=>'0');
|
||
sbuf_reg <= (others=>'0');
|
||
|
||
addr_reg <= (others => '0');
|
||
data_in_reg <= (others => '0');
|
||
data_out_reg <= (others => '0');
|
||
wren_reg <= '0';
|
||
|
||
ready_reg <= '0';
|
||
|
||
transmit_reg <= (others=>'0');
|
||
|
||
read_request_reg <= '0';
|
||
write_request_reg <= '0';
|
||
sector_reg <=(others=>'0');
|
||
elsif (clk2'event and clk2='1') then
|
||
cnt_reg <= cnt_next;
|
||
cmd_reg <= cmd_next;
|
||
sbuf_reg <= sbuf_next;
|
||
|
||
addr_reg <= addr_next;
|
||
data_in_reg <= data_in_next;
|
||
data_out_reg <= data_out_next;
|
||
wren_reg <= wren_next;
|
||
|
||
ready_reg <= ready_next;
|
||
|
||
transmit_reg <= transmit_next;
|
||
|
||
read_request_reg <= read_request_next;
|
||
write_request_reg <= write_request_next;
|
||
sector_reg <= sector_next;
|
||
end if;
|
||
end process;
|
||
|
||
-- clk_sync : synchronizer
|
||
-- PORT MAP ( CLK => clk, raw => spi_clk, sync=>spi_clk_next);
|
||
--spi_clk_next <= spi_clk;
|
||
|
||
-- input_sync : synchronizer
|
||
-- PORT MAP ( CLK => clk, raw => spi_mosi, sync=>spi_mosi_next);
|
||
|
||
-- select_sync : synchronizer
|
||
-- PORT MAP ( CLK => clk, raw => spi_ss_io, sync=>spi_ss_next);
|
||
|
||
data_in_next <= data_in;
|
||
|
||
process(spi_ss_io,cnt_reg, sbuf_reg, transmit_reg, spi_mosi, addr_reg, cmd_reg, sector_reg, write_request_reg, read_request_reg, ready_reg,read_request,write_request,sector,data_in_reg)
|
||
begin
|
||
cnt_next <= cnt_reg;
|
||
sbuf_next <= sbuf_reg;
|
||
cmd_next <= cmd_reg;
|
||
ready_next <= ready_reg and (read_request or write_request); -- stay ready until read_request cleared (received by other end)
|
||
|
||
transmit_next <= transmit_reg;
|
||
|
||
wren_next <= '0';
|
||
data_out_next <= (others=>'0');
|
||
addr_next <= addr_reg;
|
||
|
||
sector_next <= sector_reg;
|
||
read_request_next <= read_request_reg;
|
||
write_request_next <= write_request_reg;
|
||
|
||
--- It polls get_status 10 times a second
|
||
--- it uses SPI_SS2 for this
|
||
--- it sends command code 0x50
|
||
--- reads 4 bytes afterwards
|
||
|
||
--- it reports whenever the returned value is different then the one from previous get_status
|
||
|
||
--- if the lowest byte of the status (the last transmitted of the four) is 0xa5:
|
||
--- a sector is read from sd card with the sector no being the upper/first three bytes transmitted
|
||
--- if the sector could be read
|
||
--- SPI_SS2 is activated
|
||
--- command byte 0x51 is sent
|
||
--- all 512 sector bytes are sent
|
||
|
||
--if (spi_clk_reg = '1' and spi_clk_next = '0') then
|
||
transmit_next(7 downto 1) <= transmit_reg(6 downto 0);
|
||
transmit_next(0) <= '0';
|
||
|
||
cnt_next <= std_logic_vector(unsigned(cnt_reg) + 1);
|
||
|
||
sbuf_next(6 downto 1) <= sbuf_reg(5 downto 0);
|
||
sbuf_next(0) <= SPI_MOSI;
|
||
|
||
if (cnt_reg = X"0000") then
|
||
addr_next <= (others=>'0');
|
||
end if;
|
||
|
||
if (cnt_reg = X"0007") then
|
||
cmd_next(7 downto 1) <= sbuf_reg;
|
||
cmd_next(0) <= SPI_MOSI;
|
||
|
||
sector_next <= sector;
|
||
read_request_next <= read_request;
|
||
write_request_next <= write_request;
|
||
end if;
|
||
|
||
--end if;
|
||
|
||
case cmd_reg is
|
||
when X"50" => --get status
|
||
case cnt_reg is
|
||
when X"0008" =>
|
||
transmit_next <= sector_reg(25 downto 18);
|
||
when X"0010" =>
|
||
transmit_next <= sector_reg(17 downto 10);
|
||
when X"0018" =>
|
||
transmit_next <= sector_reg(9 downto 2);
|
||
when X"0020" =>
|
||
transmit_next <= sector_reg(1 downto 0)&"1010"&write_request_reg&read_request_reg; --read read_request
|
||
when others =>
|
||
-- nothing
|
||
end case;
|
||
when X"51" => --sector read from sd, write it...
|
||
if (cnt_reg = X"0008") then
|
||
addr_next <= (others=>'1');
|
||
end if;
|
||
if (cnt_reg(2 downto 0) = "111") then
|
||
addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
|
||
data_out_next(7 downto 1) <= sbuf_reg;
|
||
data_out_next(0) <= SPI_MOSI;
|
||
wren_next <= read_request;
|
||
|
||
if (cnt_reg(12) = '1')then
|
||
ready_next <= '1';
|
||
end if;
|
||
end if;
|
||
when X"52" => -- read from write, write to sd
|
||
if (cnt_reg(2 downto 0) = "000") then
|
||
addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
|
||
transmit_next <= data_in_reg;
|
||
|
||
if (cnt_reg(12) = '1')then
|
||
ready_next <= '1';
|
||
end if;
|
||
end if;
|
||
when others =>
|
||
-- nop
|
||
end case;
|
||
end process;
|
||
|
||
-- outputs
|
||
addr <= addr_next;
|
||
data_out <= data_out_next;
|
||
wr_en <= wren_next;
|
||
|
||
ready <= ready_reg;
|
||
|
||
spi_miso <= transmit_next(7);
|
||
end vhdl;
|
mist_5200/zpu_rom.vhdl | ||
---|---|---|
X"00000000",
|
||
X"00000000",
|
||
X"71fc0608",
|
||
X"0b0b80e5",
|
||
X"d0738306",
|
||
X"0b0b80dd",
|
||
X"d8738306",
|
||
X"10100508",
|
||
X"060b0b0b",
|
||
X"88a20400",
|
||
... | ... | |
X"00000000",
|
||
X"00000000",
|
||
X"00000000",
|
||
X"810b80e8",
|
||
X"f00c5104",
|
||
X"810b80e0",
|
||
X"f80c5104",
|
||
X"00000000",
|
||
X"00000000",
|
||
X"00000000",
|
||
... | ... | |
X"83e08008",
|
||
X"83e08408",
|
||
X"83e08808",
|
||
X"757580df",
|
||
X"fe2d5050",
|
||
X"757580d8",
|
||
X"872d5050",
|
||
X"83e08008",
|
||
X"5683e088",
|
||
X"0c83e084",
|
||
... | ... | |
X"e0800883",
|
||
X"e0840883",
|
||
X"e0880875",
|
||
X"7580de92",
|
||
X"7580d69b",
|
||
X"2d505083",
|
||
X"e0800856",
|
||
X"83e0880c",
|
||
... | ... | |
X"51040000",
|
||
X"800489aa",
|
||
X"0489aa0b",
|
||
X"80d9d404",
|
||
X"80cfd504",
|
||
X"f43d0d7e",
|
||
X"8f3dec11",
|
||
X"56565890",
|
||
X"53f01552",
|
||
X"775193b0",
|
||
X"775193ae",
|
||
X"3f83e080",
|
||
X"0880d638",
|
||
X"78902e09",
|
||
X"810680cd",
|
||
X"3802ab05",
|
||
X"3380e8f8",
|
||
X"0b80e8f8",
|
||
X"3380e180",
|
||
X"0b80e180",
|
||
X"33575856",
|
||
X"8c397476",
|
||
X"2e8a3884",
|
||
... | ... | |
X"56705556",
|
||
X"5696800a",
|
||
X"52775192",
|
||
X"df3f83e0",
|
||
X"dd3f83e0",
|
||
X"80088638",
|
||
X"78752e85",
|
||
X"38805685",
|
||
... | ... | |
X"800c8e3d",
|
||
X"0d04fc3d",
|
||
X"0d767052",
|
||
X"55b3923f",
|
||
X"55b3903f",
|
||
X"83e08008",
|
||
X"15ff0554",
|
||
X"73752e8e",
|
||
... | ... | |
X"38ff1454",
|
||
X"ef397752",
|
||
X"811451b2",
|
||
X"aa3f83e0",
|
||
X"a83f83e0",
|
||
X"80083070",
|
||
X"83e08008",
|
||
X"07802583",
|
||
... | ... | |
X"863d0d04",
|
||
X"fc3d0d76",
|
||
X"70525599",
|
||
X"cb3f83e0",
|
||
X"c93f83e0",
|
||
X"80085481",
|
||
X"5383e080",
|
||
X"0880c738",
|
||
X"7451998e",
|
||
X"7451998c",
|
||
X"3f83e080",
|
||
X"080b0b80",
|
||
X"e7b05383",
|
||
X"dfb85383",
|
||
X"e0800852",
|
||
X"53ff8f3f",
|
||
X"83e08008",
|
||
X"a5380b0b",
|
||
X"80e7b452",
|
||
X"80dfbc52",
|
||
X"7251fefe",
|
||
X"3f83e080",
|
||
X"0894380b",
|
||
X"0b80e7b8",
|
||
X"0b80dfc0",
|
||
X"527251fe",
|
||
X"ed3f83e0",
|
||
X"8008802e",
|
||
... | ... | |
X"e0800c86",
|
||
X"3d0d04fd",
|
||
X"3d0d7570",
|
||
X"525498e4",
|
||
X"525498e2",
|
||
X"3f815383",
|
||
X"e0800898",
|
||
X"38735198",
|
||
X"ad3f83e0",
|
||
X"ab3f83e0",
|
||
X"a0085283",
|
||
X"e0800851",
|
||
X"feb43f83",
|
||
... | ... | |
X"0c853d0d",
|
||
X"04e03d0d",
|
||
X"a33d0870",
|
||
X"525e8ed3",
|
||
X"525e8ed1",
|
||
X"3f83e080",
|
||
X"0833943d",
|
||
X"56547394",
|
||
X"3880ea80",
|
||
X"3880e288",
|
||
X"52745184",
|
||
X"c7397d52",
|
||
X"785191d6",
|
||
X"3f84d139",
|
||
X"7d518ebb",
|
||
X"c6397d52",
|
||
X"785191d4",
|
||
X"3f84d039",
|
||
X"7d518eb9",
|
||
X"3f83e080",
|
||
X"08527451",
|
||
X"8deb3f83",
|
||
X"8de93f83",
|
||
X"e0a80852",
|
||
X"933d7052",
|
||
X"5d94c63f",
|
||
X"5d94c43f",
|
||
X"83e08008",
|
||
X"59800b83",
|
||
X"e0800855",
|
||
X"5b83e080",
|
||
X"087b2e94",
|
||
X"38811b74",
|
||
X"525b97c7",
|
||
X"525b97c5",
|
||
X"3f83e080",
|
||
X"085483e0",
|
||
X"8008ee38",
|
||
... | ... | |
X"5a525555",
|
||
X"80752595",
|
||
X"38765197",
|
||
X"863f83e0",
|
||
X"843f83e0",
|
||
X"800876ff",
|
||
X"18585557",
|
||
X"738024ed",
|
||
X"38747f2e",
|
||
X"873880c2",
|
||
X"db3f745f",
|
||
X"78ff1b70",
|
||
X"585d5880",
|
||
X"7a259538",
|
||
X"775196db",
|
||
X"8638b8dd",
|
||
X"3f745f78",
|
||
X"ff1b7058",
|
||
X"5d58807a",
|
||
X"25953877",
|
||
X"5196da3f",
|
||
X"83e08008",
|
||
X"76ff1858",
|
||
X"55587380",
|
||
X"24ed3880",
|
||
X"0b83e3a8",
|
||
X"0c800b83",
|
||
X"e3cc0c0b",
|
||
X"0b80dfc4",
|
||
X"518bad3f",
|
||
X"81800b83",
|
||
X"e3cc0c0b",
|
||
X"0b80dfcc",
|
||
X"518b9d3f",
|
||
X"a80b83e3",
|
||
X"a80c7680",
|
||
X"2e80e838",
|
||
X"83e3a808",
|
||
X"77793270",
|
||
X"30707207",
|
||
X"80257087",
|
||
X"2b83e3cc",
|
||
X"0c515678",
|
||
X"53565696",
|
||
X"8d3f83e0",
|
||
X"8008802e",
|
||
X"8a380b0b",
|
||
X"80dfd451",
|
||
X"8ae23f76",
|
||
X"5195cd3f",
|
||
X"83e08008",
|
||
X"520b0b80",
|
||
X"e088518a",
|
||
X"cf3f7651",
|
||
X"95d33f83",
|
||
X"e0800883",
|
||
X"e3a80855",
|
||
X"57757425",
|
||
X"8638a816",
|
||
X"56f73975",
|
||
X"83e3a80c",
|
||
X"86f07624",
|
||
X"ff943887",
|
||
X"980b83e3",
|
||
X"a80c7780",
|
||
X"2eb73877",
|
||
X"5195893f",
|
||
X"83e08008",
|
||
X"78525595",
|
||
X"a93f0b0b",
|
||
X"80dfdc54",
|
||
X"83e08008",
|
||
X"8f388739",
|
||
X"807634fd",
|
||
X"96390b0b",
|
||
X"80dfd854",
|
||
X"74537352",
|
||
X"0b0b80df",
|
||
X"a85189e8",
|
||
X"3f80540b",
|
||
X"0b80dfb0",
|
||
X"5189dd3f",
|
||
X"81145473",
|
||
X"a82e0981",
|
||
X"06ed3886",
|
||
X"8da051b4",
|
||
X"d33f8052",
|
||
X"903d7052",
|
||
X"5480c2e7",
|
||
X"3f835273",
|
||
X"5180c2df",
|
||
X"3f61802e",
|
||
X"80ff387b",
|
||
X"5473ff2e",
|
||
X"96387880",
|
||
X"2e818038",
|
||
X"785194a9",
|
||
X"3f83e080",
|
||
X"0876ff18",
|
||
X"58555873",
|
||
X"8024ed38",
|
||
X"800b83e7",
|
||
X"bc0c800b",
|
||
X"83e7e00c",
|
||
X"0b0b80e7",
|
||
X"bc518bae",
|
||
X"3f81800b",
|
||
X"83e7e00c",
|
||
X"0b0b80e7",
|
||
X"c4518b9e",
|
||
X"3fa80b83",
|
||
X"e7bc0c76",
|
||
X"802e80e8",
|
||
X"3883e7bc",
|
||
X"08777932",
|
||
X"70307072",
|
||
X"07802570",
|
||
X"872b83e7",
|
||
X"e00c5156",
|
||
X"78535656",
|
||
X"968e3f83",
|
||
X"e0800880",
|
||
X"2e8a380b",
|
||
X"0b80e7cc",
|
||
X"518ae33f",
|
||
X"765195ce",
|
||
X"3f83e080",
|
||
X"08520b0b",
|
||
X"80e88051",
|
||
X"8ad03f76",
|
||
X"5195d43f",
|
||
X"08ff1555",
|
||
X"59e73978",
|
||
X"802e80eb",
|
||
X"38785194",
|
||
X"a53f83e0",
|
||
X"8008802e",
|
||
X"fc843878",
|
||
X"5193ed3f",
|
||
X"83e08008",
|
||
X"83e7bc08",
|
||
X"55577574",
|
||
X"258638a8",
|
||
X"1656f739",
|
||
X"7583e7bc",
|
Also available in: Unified diff
Some 5200 fixes, reverted to data_io mist interface