|
//
|
|
// data_io.v
|
|
//
|
|
// data_io for the MiST board
|
|
// http://code.google.com/p/mist-board/
|
|
//
|
|
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
|
// Copyright (c) 2015-2017 Sorgelig
|
|
// Copyright (c) 2019 György Szombathelyi
|
|
//
|
|
// This source file 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.
|
|
//
|
|
// 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/>.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
module data_io
|
|
(
|
|
// Global clock. It should be around 100MHz (higher is better).
|
|
input clk_sys,
|
|
|
|
// Global SPI clock from ARM. 24MHz
|
|
input SPI_SCK,
|
|
input SPI_SS2,
|
|
input SPI_DI,
|
|
|
|
// ARM -> FPGA download
|
|
input ioctl_wait,
|
|
output reg ioctl_download = 0, // signal indicating an active download
|
|
output reg [7:0] ioctl_index, // menu index used to upload the file
|
|
output reg ioctl_wr = 0,
|
|
output reg [24:0] ioctl_addr,
|
|
output reg [15:0] ioctl_dout
|
|
);
|
|
|
|
/////////////////////////////// DOWNLOADING ///////////////////////////////
|
|
|
|
localparam UIO_FILE_TX = 8'h53;
|
|
localparam UIO_FILE_TX_DAT = 8'h54;
|
|
localparam UIO_FILE_INDEX = 8'h55;
|
|
// SPI receiver IO -> FPGA
|
|
|
|
reg spi_receiver_strobe_r = 0;
|
|
reg spi_transfer_end_r = 1;
|
|
reg [7:0] spi_byte_in;
|
|
|
|
// data_io has its own SPI interface to the io controller
|
|
// Read at spi_sck clock domain, assemble bytes for transferring to clk_sys
|
|
always@(posedge SPI_SCK or posedge SPI_SS2) begin
|
|
|
|
reg [6:0] sbuf;
|
|
reg [2:0] bit_cnt;
|
|
|
|
if(SPI_SS2) begin
|
|
spi_transfer_end_r <= 1;
|
|
bit_cnt <= 0;
|
|
end else begin
|
|
spi_transfer_end_r <= 0;
|
|
|
|
bit_cnt <= bit_cnt + 1'd1;
|
|
|
|
if(bit_cnt != 7)
|
|
sbuf[6:0] <= { sbuf[5:0], SPI_DI };
|
|
|
|
// finished reading a byte, prepare to transfer to clk_sys
|
|
if(bit_cnt == 7) begin
|
|
spi_byte_in <= { sbuf, SPI_DI};
|
|
spi_receiver_strobe_r <= ~spi_receiver_strobe_r;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clk_sys) begin
|
|
|
|
reg spi_receiver_strobe;
|
|
reg spi_transfer_end;
|
|
reg spi_receiver_strobeD;
|
|
reg spi_transfer_endD;
|
|
reg [7:0] acmd;
|
|
reg [2:0] abyte_cnt; // counts bytes
|
|
reg [24:0] addr;
|
|
reg wr_int;
|
|
reg clkrefD;
|
|
reg hi;
|
|
|
|
//synchronize between SPI and sys 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 (~spi_transfer_endD & spi_transfer_end) begin
|
|
abyte_cnt <= 3'd0;
|
|
end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin
|
|
if(~&abyte_cnt) abyte_cnt <= abyte_cnt + 1'd1;
|
|
|
|
if(abyte_cnt == 0) begin
|
|
acmd <= spi_byte_in;
|
|
hi <= 0;
|
|
end else begin
|
|
case (acmd)
|
|
UIO_FILE_TX: begin
|
|
// prepare
|
|
if(spi_byte_in) begin
|
|
addr <= 25'h804000;
|
|
ioctl_download <= 1;
|
|
end else begin
|
|
ioctl_addr <= addr;
|
|
ioctl_download <= 0;
|
|
end
|
|
end
|
|
|
|
// transfer
|
|
UIO_FILE_TX_DAT: begin
|
|
ioctl_addr <= addr;
|
|
if (hi) ioctl_dout[15:8] <= spi_byte_in; else ioctl_dout[7:0] <= spi_byte_in;
|
|
hi <= ~hi;
|
|
if (hi) wr_int <= 1;
|
|
end
|
|
|
|
// expose file (menu) index
|
|
UIO_FILE_INDEX: ioctl_index <= spi_byte_in;
|
|
endcase
|
|
end
|
|
end
|
|
|
|
ioctl_wr <= 0;
|
|
if (wr_int & ~ioctl_wait) begin
|
|
addr <= addr + 2'd2;
|
|
ioctl_wr <= 1;
|
|
wr_int <= 0;
|
|
end
|
|
end
|
|
|
|
endmodule
|