mirror of
https://github.com/nippur72/Apple1_MiST.git
synced 2024-09-27 09:55:45 +00:00
module downloader
This commit is contained in:
parent
6edb71037a
commit
04f501511f
@ -154,6 +154,7 @@ set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
|||||||
|
|
||||||
# end ENTITY(apple1_mist)
|
# end ENTITY(apple1_mist)
|
||||||
# -----------------------
|
# -----------------------
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/downloader.sv
|
||||||
set_global_assignment -name VERILOG_FILE rtl/display.v
|
set_global_assignment -name VERILOG_FILE rtl/display.v
|
||||||
set_global_assignment -name VERILOG_FILE rtl/sdram.v
|
set_global_assignment -name VERILOG_FILE rtl/sdram.v
|
||||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/user_io.v"
|
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/user_io.v"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
// TODO support ACI interface for load and save
|
// TODO support ACI interface for load and save
|
||||||
// TODO special expansion boards: TMS9918, SID
|
// TODO special expansion boards: TMS9918, SID
|
||||||
// TODO ascii keyboard
|
// TODO ascii keyboard
|
||||||
|
// TODO check diff with updated data_io.v
|
||||||
|
|
||||||
module apple1_mist(
|
module apple1_mist(
|
||||||
input CLOCK_27,
|
input CLOCK_27,
|
||||||
@ -27,9 +28,9 @@ module apple1_mist(
|
|||||||
input SPI_SCK,
|
input SPI_SCK,
|
||||||
output SPI_DO,
|
output SPI_DO,
|
||||||
input SPI_DI,
|
input SPI_DI,
|
||||||
//input SPI_SS2,
|
input SPI_SS2,
|
||||||
input SPI_SS3,
|
input SPI_SS3,
|
||||||
//input SPI_SS4,
|
input SPI_SS4,
|
||||||
input CONF_DATA0,
|
input CONF_DATA0,
|
||||||
|
|
||||||
// SDRAM interface
|
// SDRAM interface
|
||||||
@ -68,7 +69,9 @@ module apple1_mist(
|
|||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
|
|
||||||
localparam CONF_STR = {
|
localparam CONF_STR = {
|
||||||
"APPLE 1;;",
|
"APPLE 1;;", // 0 download index for "apple1.rom"
|
||||||
|
"F,PRG,Load program;", // 1 download index for ".prg" files
|
||||||
|
"F,ROM,Load firmware;", // 2 download index for ".rom" files
|
||||||
"O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
"O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
||||||
"T6,Reset;",
|
"T6,Reset;",
|
||||||
"V,v1.01.",`BUILD_DATE
|
"V,v1.01.",`BUILD_DATE
|
||||||
@ -95,8 +98,6 @@ wire no_csync;
|
|||||||
wire ps2_kbd_clk;
|
wire ps2_kbd_clk;
|
||||||
wire ps2_kbd_data;
|
wire ps2_kbd_data;
|
||||||
|
|
||||||
assign LED = 1;
|
|
||||||
|
|
||||||
wire reset_button = status[0] | st_menu_reset | st_reset_switch | !pll_locked;
|
wire reset_button = status[0] | st_menu_reset | st_reset_switch | !pll_locked;
|
||||||
|
|
||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
@ -120,6 +121,48 @@ pll pll
|
|||||||
*/
|
*/
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/******************************************************************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
/***************************************** @downloader ************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
|
||||||
|
wire is_downloading; // indicates that downloader is working
|
||||||
|
wire [24:0] download_addr; // download address
|
||||||
|
wire [7:0] download_data; // download data
|
||||||
|
wire download_wr; // download write enable
|
||||||
|
wire ROM_loaded; // 1 when boot rom has been downloaded
|
||||||
|
|
||||||
|
// ROM download helper
|
||||||
|
downloader
|
||||||
|
#(
|
||||||
|
.BOOT_INDEX (0), // menu index 0 is for automatic download of "apple1.rom" at FPGA boot
|
||||||
|
.PRG_INDEX (1), // menu index for load .prg
|
||||||
|
.ROM_INDEX (2), // menu index for load .prg
|
||||||
|
.ROM_START_ADDR(0) // start of ROM (bank 0 of SDRAM)
|
||||||
|
)
|
||||||
|
downloader
|
||||||
|
(
|
||||||
|
// new SPI interface
|
||||||
|
.SPI_DO ( SPI_DO ),
|
||||||
|
.SPI_DI ( SPI_DI ),
|
||||||
|
.SPI_SCK( SPI_SCK ),
|
||||||
|
.SPI_SS2( SPI_SS2 ),
|
||||||
|
.SPI_SS3( SPI_SS3 ),
|
||||||
|
.SPI_SS4( SPI_SS4 ),
|
||||||
|
|
||||||
|
// signal indicating an active rom download
|
||||||
|
.downloading ( is_downloading ),
|
||||||
|
.ROM_done ( ROM_loaded ),
|
||||||
|
|
||||||
|
// external ram interface
|
||||||
|
.clk ( clk14 ),
|
||||||
|
.clk_ena ( 1 ),
|
||||||
|
.wr ( download_wr ),
|
||||||
|
.addr ( download_addr ),
|
||||||
|
.data ( download_data )
|
||||||
|
);
|
||||||
|
|
||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
/***************************************** @apple1 ****************************************/
|
/***************************************** @apple1 ****************************************/
|
||||||
@ -127,15 +170,50 @@ pll pll
|
|||||||
/******************************************************************************************/
|
/******************************************************************************************/
|
||||||
|
|
||||||
// RAM
|
// RAM
|
||||||
wire [7:0] ram_dout;
|
|
||||||
ram ram(
|
ram ram(
|
||||||
.clk(clk14),
|
.clk (clk14 ),
|
||||||
.address(cpu_addr[12:0]),
|
.address(sdram_addr[12:0]),
|
||||||
.w_en(cpu_wr),
|
.w_en (sdram_wr ),
|
||||||
.din(cpu_dout),
|
.din (sdram_din ),
|
||||||
.dout(ram_dout)
|
.dout (sdram_dout)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// SDRAM control signals
|
||||||
|
//assign SDRAM_CKE = 1'b1;
|
||||||
|
|
||||||
|
wire [24:0] sdram_addr;
|
||||||
|
wire [7:0] sdram_din;
|
||||||
|
wire sdram_wr;
|
||||||
|
wire sdram_rd;
|
||||||
|
wire [7:0] sdram_dout;
|
||||||
|
|
||||||
|
assign dummy = is_downloading && download_wr;
|
||||||
|
|
||||||
|
always @(*) begin
|
||||||
|
if(is_downloading && download_wr) begin
|
||||||
|
sdram_addr <= download_addr;
|
||||||
|
sdram_din <= download_data;
|
||||||
|
sdram_wr <= download_wr;
|
||||||
|
sdram_rd <= 1'b1;
|
||||||
|
end
|
||||||
|
/*
|
||||||
|
else if(eraser_busy) begin
|
||||||
|
sdram_addr <= eraser_addr;
|
||||||
|
sdram_din <= eraser_data;
|
||||||
|
sdram_wr <= eraser_wr;
|
||||||
|
sdram_rd <= 1'b1;
|
||||||
|
end
|
||||||
|
*/
|
||||||
|
else begin
|
||||||
|
sdram_addr <= { 12'b0, cpu_addr[12:0] };
|
||||||
|
sdram_din <= cpu_dout;
|
||||||
|
sdram_wr <= cpu_wr;
|
||||||
|
sdram_rd <= cpu_rd;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign LED = ~dummy;
|
||||||
|
|
||||||
// WozMon ROM
|
// WozMon ROM
|
||||||
wire [7:0] rom_dout;
|
wire [7:0] rom_dout;
|
||||||
rom_wozmon rom_wozmon(
|
rom_wozmon rom_wozmon(
|
||||||
@ -164,7 +242,7 @@ wire rom_cs = (cpu_addr[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
|
|||||||
|
|
||||||
wire [7:0] bus_dout = basic_cs ? basic_dout :
|
wire [7:0] bus_dout = basic_cs ? basic_dout :
|
||||||
rom_cs ? rom_dout :
|
rom_cs ? rom_dout :
|
||||||
ram_cs ? ram_dout :
|
ram_cs ? sdram_dout :
|
||||||
8'b0;
|
8'b0;
|
||||||
|
|
||||||
|
|
||||||
|
111
rtl/downloader.sv
Normal file
111
rtl/downloader.sv
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// This module allows easy download of three types of files into system ram:
|
||||||
|
//
|
||||||
|
// 1) ROM file that is injected by the firmware at startup/boot (loaded at address 0)
|
||||||
|
// 2) PRG file, containing load address in the first two bytes as in C64's .prg
|
||||||
|
// 3) ROM as 1) but with different .rom file name selected by the user from the menu
|
||||||
|
|
||||||
|
|
||||||
|
module downloader (
|
||||||
|
|
||||||
|
// SPI interface with the ARM controller
|
||||||
|
input SPI_DO,
|
||||||
|
input SPI_DI,
|
||||||
|
input SPI_SCK,
|
||||||
|
input SPI_SS2,
|
||||||
|
input SPI_SS3,
|
||||||
|
input SPI_SS4,
|
||||||
|
|
||||||
|
input clk,
|
||||||
|
input clk_ena,
|
||||||
|
|
||||||
|
output reg wr,
|
||||||
|
output reg [24:0] addr,
|
||||||
|
output reg [7:0] data,
|
||||||
|
|
||||||
|
output reg downloading, // 1 = active download is in process
|
||||||
|
output reg ROM_done // 1 = boot ROM has already been loaded
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BOOT_INDEX = 0; // menu index for the boot rom (0 by default in MiST firmware)
|
||||||
|
parameter PRG_INDEX; // menu index for .prg files
|
||||||
|
parameter ROM_INDEX; // menu index for .rom files (not loaded at boot)
|
||||||
|
parameter ROM_START_ADDR = 0; // start of ROM
|
||||||
|
|
||||||
|
reg [15:0] prg_start_addr; // first two bytes of the .prg file containing ram loading address
|
||||||
|
|
||||||
|
// simplify checks
|
||||||
|
wire is_rom_download = dio_index == BOOT_INDEX || dio_index == ROM_INDEX;
|
||||||
|
wire is_prg_download = dio_index == PRG_INDEX;
|
||||||
|
|
||||||
|
reg dio_dowloading_old = 0; // used to detect changes in dio_dowloading
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
|
||||||
|
if(dio_dowloading == 1) begin
|
||||||
|
downloading <= 1;
|
||||||
|
|
||||||
|
if(is_rom_download) begin
|
||||||
|
addr <= dio_addr + ROM_START_ADDR;
|
||||||
|
wr <= dio_wr;
|
||||||
|
data <= dio_data;
|
||||||
|
end
|
||||||
|
else if(is_prg_download) begin
|
||||||
|
if(dio_addr == 0) begin
|
||||||
|
prg_start_addr [7:0] = dio_data; // extracts address low byte
|
||||||
|
wr <= 0; // do not write yet
|
||||||
|
end
|
||||||
|
else if(dio_addr == 1) begin
|
||||||
|
prg_start_addr[15:8] = dio_data; // extracts address high byte
|
||||||
|
wr <= 0; // do not write yet
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
addr <= dio_addr + { 9'b0, prg_start_addr } - 2; // write prg at load address and skip first two bytes
|
||||||
|
wr <= dio_wr;
|
||||||
|
data <= dio_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// end of transfer
|
||||||
|
if(dio_dowloading_old == 1 && dio_dowloading == 0) begin
|
||||||
|
downloading <= 0;
|
||||||
|
if(is_rom_download) ROM_done <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
// detect change in dio_dowloading
|
||||||
|
dio_dowloading_old <= dio_dowloading;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
/******************************************************************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
/***************************************** @data_io ***************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
/******************************************************************************************/
|
||||||
|
|
||||||
|
wire dio_dowloading;
|
||||||
|
wire [7:0] dio_index;
|
||||||
|
wire dio_wr;
|
||||||
|
wire [24:0] dio_addr;
|
||||||
|
wire [7:0] dio_data;
|
||||||
|
|
||||||
|
data_io data_io (
|
||||||
|
.clk_sys ( clk ),
|
||||||
|
.clkref_n( ~clk_ena ), // keep this to zero
|
||||||
|
|
||||||
|
// io controller spi interface
|
||||||
|
.SPI_SCK( SPI_SCK ),
|
||||||
|
.SPI_SS2( SPI_SS2 ),
|
||||||
|
.SPI_SS4( SPI_SS4 ),
|
||||||
|
.SPI_DI ( SPI_DI ),
|
||||||
|
.SPI_DO ( SPI_DO ),
|
||||||
|
|
||||||
|
.ioctl_download ( dio_dowloading ), // signal indicating an active rom download
|
||||||
|
.ioctl_index ( dio_index ), // 0=rom download, 1=prg dowload
|
||||||
|
.ioctl_addr ( dio_addr ),
|
||||||
|
.ioctl_dout ( dio_data ),
|
||||||
|
.ioctl_wr ( dio_wr )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
259
rtl/mist-modules/_new__data_io.v
Normal file
259
rtl/mist-modules/_new__data_io.v
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
//
|
||||||
|
// data_io.v
|
||||||
|
//
|
||||||
|
// data_io for the MiST board
|
||||||
|
// http://code.google.com/p/mist-board/
|
||||||
|
//
|
||||||
|
// 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 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
|
||||||
|
(
|
||||||
|
input clk_sys,
|
||||||
|
input SPI_SCK,
|
||||||
|
input SPI_SS2,
|
||||||
|
input SPI_SS4,
|
||||||
|
input SPI_DI,
|
||||||
|
inout SPI_DO,
|
||||||
|
|
||||||
|
input clkref_n, // assert ioctl_wr one cycle after clkref stobe (negative active)
|
||||||
|
|
||||||
|
// ARM -> FPGA download
|
||||||
|
output reg ioctl_download = 0, // signal indicating an active download
|
||||||
|
output reg ioctl_upload = 0, // signal indicating an active upload
|
||||||
|
output reg [7:0] ioctl_index, // menu index used to upload the file ([7:6] - extension index, [5:0] - menu index)
|
||||||
|
// Note: this is also set for user_io mounts.
|
||||||
|
// Valid when ioctl_download = 1 or when img_mounted strobe is active in user_io.
|
||||||
|
output reg ioctl_wr, // strobe indicating ioctl_dout valid
|
||||||
|
output reg [24:0] ioctl_addr,
|
||||||
|
output reg [7:0] ioctl_dout,
|
||||||
|
input [7:0] ioctl_din,
|
||||||
|
output reg [23:0] ioctl_fileext, // file extension
|
||||||
|
output reg [31:0] ioctl_filesize // file size
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter START_ADDR = 25'd0;
|
||||||
|
parameter ROM_DIRECT_UPLOAD = 0;
|
||||||
|
|
||||||
|
/////////////////////////////// DOWNLOADING ///////////////////////////////
|
||||||
|
|
||||||
|
reg [7:0] data_w;
|
||||||
|
reg [7:0] data_w2 = 0;
|
||||||
|
reg [3:0] cnt;
|
||||||
|
reg rclk = 0;
|
||||||
|
reg rclk2 = 0;
|
||||||
|
reg addr_reset = 0;
|
||||||
|
reg downloading_reg = 0;
|
||||||
|
reg uploading_reg = 0;
|
||||||
|
reg reg_do;
|
||||||
|
|
||||||
|
localparam DIO_FILE_TX = 8'h53;
|
||||||
|
localparam DIO_FILE_TX_DAT = 8'h54;
|
||||||
|
localparam DIO_FILE_INDEX = 8'h55;
|
||||||
|
localparam DIO_FILE_INFO = 8'h56;
|
||||||
|
localparam DIO_FILE_RX = 8'h57;
|
||||||
|
localparam DIO_FILE_RX_DAT = 8'h58;
|
||||||
|
|
||||||
|
assign SPI_DO = reg_do;
|
||||||
|
|
||||||
|
// data_io has its own SPI interface to the io controller
|
||||||
|
always@(negedge SPI_SCK or posedge SPI_SS2) begin : SPI_TRANSMITTER
|
||||||
|
reg [7:0] dout_r;
|
||||||
|
|
||||||
|
if(SPI_SS2) begin
|
||||||
|
reg_do <= 1'bZ;
|
||||||
|
end else begin
|
||||||
|
if (cnt == 15) dout_r <= ioctl_din;
|
||||||
|
reg_do <= dout_r[~cnt[2:0]];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
||||||
|
reg [6:0] sbuf;
|
||||||
|
reg [24:0] addr;
|
||||||
|
reg [7:0] cmd;
|
||||||
|
reg [5:0] bytecnt;
|
||||||
|
|
||||||
|
if(SPI_SS2) begin
|
||||||
|
bytecnt <= 0;
|
||||||
|
cnt <= 0;
|
||||||
|
end else begin
|
||||||
|
// don't shift in last bit. It is evaluated directly
|
||||||
|
// when writing to ram
|
||||||
|
if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};
|
||||||
|
|
||||||
|
// count 0-7 8-15 8-15 ...
|
||||||
|
if(cnt != 15) cnt <= cnt + 1'd1;
|
||||||
|
else cnt <= 8;
|
||||||
|
|
||||||
|
// finished command byte
|
||||||
|
if(cnt == 7) cmd <= {sbuf, SPI_DI};
|
||||||
|
|
||||||
|
if(cnt == 15) begin
|
||||||
|
case (cmd)
|
||||||
|
// prepare/end transmission
|
||||||
|
DIO_FILE_TX: begin
|
||||||
|
// prepare
|
||||||
|
if(SPI_DI) begin
|
||||||
|
addr_reset <= ~addr_reset;
|
||||||
|
downloading_reg <= 1;
|
||||||
|
end else begin
|
||||||
|
downloading_reg <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DIO_FILE_RX: begin
|
||||||
|
// prepare
|
||||||
|
if(SPI_DI) begin
|
||||||
|
addr_reset <= ~addr_reset;
|
||||||
|
uploading_reg <= 1;
|
||||||
|
end else begin
|
||||||
|
uploading_reg <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// command 0x57: DIO_FILE_RX_DAT
|
||||||
|
// command 0x54: DIO_FILE_TX_DAT
|
||||||
|
DIO_FILE_RX_DAT,
|
||||||
|
DIO_FILE_TX_DAT: begin
|
||||||
|
data_w <= {sbuf, SPI_DI};
|
||||||
|
rclk <= ~rclk;
|
||||||
|
end
|
||||||
|
|
||||||
|
// expose file (menu) index
|
||||||
|
DIO_FILE_INDEX: ioctl_index <= {sbuf, SPI_DI};
|
||||||
|
|
||||||
|
// receiving FAT directory entry (mist-firmware/fat.h - DIRENTRY)
|
||||||
|
DIO_FILE_INFO: begin
|
||||||
|
bytecnt <= bytecnt + 1'd1;
|
||||||
|
case (bytecnt)
|
||||||
|
8'h08: ioctl_fileext[23:16] <= {sbuf, SPI_DI};
|
||||||
|
8'h09: ioctl_fileext[15: 8] <= {sbuf, SPI_DI};
|
||||||
|
8'h0A: ioctl_fileext[ 7: 0] <= {sbuf, SPI_DI};
|
||||||
|
8'h1C: ioctl_filesize[ 7: 0] <= {sbuf, SPI_DI};
|
||||||
|
8'h1D: ioctl_filesize[15: 8] <= {sbuf, SPI_DI};
|
||||||
|
8'h1E: ioctl_filesize[23:16] <= {sbuf, SPI_DI};
|
||||||
|
8'h1F: ioctl_filesize[31:24] <= {sbuf, SPI_DI};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// direct SD Card->FPGA transfer
|
||||||
|
generate if (ROM_DIRECT_UPLOAD == 1) begin
|
||||||
|
|
||||||
|
always@(posedge SPI_SCK, posedge SPI_SS4) begin : SPI_DIRECT_RECEIVER
|
||||||
|
reg [6:0] sbuf2;
|
||||||
|
reg [2:0] cnt2;
|
||||||
|
reg [9:0] bytecnt;
|
||||||
|
|
||||||
|
if(SPI_SS4) begin
|
||||||
|
cnt2 <= 0;
|
||||||
|
bytecnt <= 0;
|
||||||
|
end else begin
|
||||||
|
// don't shift in last bit. It is evaluated directly
|
||||||
|
// when writing to ram
|
||||||
|
if(cnt2 != 7)
|
||||||
|
sbuf2 <= { sbuf2[5:0], SPI_DO };
|
||||||
|
|
||||||
|
cnt2 <= cnt2 + 1'd1;
|
||||||
|
|
||||||
|
// received a byte
|
||||||
|
if(cnt2 == 7) begin
|
||||||
|
bytecnt <= bytecnt + 1'd1;
|
||||||
|
// read 514 byte/sector (512 + 2 CRC)
|
||||||
|
if (bytecnt == 513) bytecnt <= 0;
|
||||||
|
// don't send the CRC bytes
|
||||||
|
if (~bytecnt[9]) begin
|
||||||
|
data_w2 <= {sbuf2, SPI_DO};
|
||||||
|
rclk2 <= ~rclk2;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
always@(posedge clk_sys) begin : DATA_OUT
|
||||||
|
// synchronisers
|
||||||
|
reg rclkD, rclkD2;
|
||||||
|
reg rclk2D, rclk2D2;
|
||||||
|
reg addr_resetD, addr_resetD2;
|
||||||
|
|
||||||
|
reg wr_int, wr_int_direct, rd_int;
|
||||||
|
reg [24:0] addr;
|
||||||
|
reg [31:0] filepos;
|
||||||
|
|
||||||
|
// bring flags from spi clock domain into core clock domain
|
||||||
|
{ rclkD, rclkD2 } <= { rclk, rclkD };
|
||||||
|
{ rclk2D ,rclk2D2 } <= { rclk2, rclk2D };
|
||||||
|
{ addr_resetD, addr_resetD2 } <= { addr_reset, addr_resetD };
|
||||||
|
|
||||||
|
ioctl_wr <= 0;
|
||||||
|
|
||||||
|
if (!downloading_reg) begin
|
||||||
|
ioctl_download <= 0;
|
||||||
|
wr_int <= 0;
|
||||||
|
wr_int_direct <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (!uploading_reg) begin
|
||||||
|
ioctl_upload <= 0;
|
||||||
|
rd_int <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (~clkref_n) begin
|
||||||
|
rd_int <= 0;
|
||||||
|
wr_int <= 0;
|
||||||
|
wr_int_direct <= 0;
|
||||||
|
if (wr_int || wr_int_direct) begin
|
||||||
|
ioctl_dout <= wr_int ? data_w : data_w2;
|
||||||
|
ioctl_wr <= 1;
|
||||||
|
addr <= addr + 1'd1;
|
||||||
|
ioctl_addr <= addr;
|
||||||
|
end
|
||||||
|
if (rd_int) begin
|
||||||
|
ioctl_addr <= ioctl_addr + 1'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// detect transfer start from the SPI receiver
|
||||||
|
if(addr_resetD ^ addr_resetD2) begin
|
||||||
|
addr <= START_ADDR;
|
||||||
|
ioctl_addr <= START_ADDR;
|
||||||
|
filepos <= 0;
|
||||||
|
ioctl_download <= downloading_reg;
|
||||||
|
ioctl_upload <= uploading_reg;
|
||||||
|
end
|
||||||
|
|
||||||
|
// detect new byte from the SPI receiver
|
||||||
|
if (rclkD ^ rclkD2) begin
|
||||||
|
wr_int <= downloading_reg;
|
||||||
|
rd_int <= uploading_reg;
|
||||||
|
end
|
||||||
|
// direct transfer receiver
|
||||||
|
if (rclk2D ^ rclk2D2 && filepos != ioctl_filesize) begin
|
||||||
|
filepos <= filepos + 1'd1;
|
||||||
|
wr_int_direct <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -28,20 +28,18 @@ module data_io
|
|||||||
input SPI_SS2,
|
input SPI_SS2,
|
||||||
input SPI_SS4,
|
input SPI_SS4,
|
||||||
input SPI_DI,
|
input SPI_DI,
|
||||||
inout SPI_DO,
|
input SPI_DO, // yes, SPI_DO is input when SS4 active
|
||||||
|
|
||||||
input clkref_n, // assert ioctl_wr one cycle after clkref stobe (negative active)
|
input clkref_n, // assert ioctl_wr one cycle after clkref stobe (negative active)
|
||||||
|
|
||||||
// ARM -> FPGA download
|
// ARM -> FPGA download
|
||||||
output reg ioctl_download = 0, // signal indicating an active download
|
output reg ioctl_download = 0, // signal indicating an active download
|
||||||
output reg ioctl_upload = 0, // signal indicating an active upload
|
|
||||||
output reg [7:0] ioctl_index, // menu index used to upload the file ([7:6] - extension index, [5:0] - menu index)
|
output reg [7:0] ioctl_index, // menu index used to upload the file ([7:6] - extension index, [5:0] - menu index)
|
||||||
// Note: this is also set for user_io mounts.
|
// Note: this is also set for user_io mounts.
|
||||||
// Valid when ioctl_download = 1 or when img_mounted strobe is active in user_io.
|
// Valid when ioctl_download = 1 or when img_mounted strobe is active in user_io.
|
||||||
output reg ioctl_wr, // strobe indicating ioctl_dout valid
|
output reg ioctl_wr, // strobe indicating ioctl_dout valid
|
||||||
output reg [24:0] ioctl_addr,
|
output reg [24:0] ioctl_addr,
|
||||||
output reg [7:0] ioctl_dout,
|
output reg [7:0] ioctl_dout,
|
||||||
input [7:0] ioctl_din,
|
|
||||||
output reg [23:0] ioctl_fileext, // file extension
|
output reg [23:0] ioctl_fileext, // file extension
|
||||||
output reg [31:0] ioctl_filesize // file size
|
output reg [31:0] ioctl_filesize // file size
|
||||||
);
|
);
|
||||||
@ -53,41 +51,23 @@ parameter ROM_DIRECT_UPLOAD = 0;
|
|||||||
|
|
||||||
reg [7:0] data_w;
|
reg [7:0] data_w;
|
||||||
reg [7:0] data_w2 = 0;
|
reg [7:0] data_w2 = 0;
|
||||||
reg [3:0] cnt;
|
|
||||||
reg rclk = 0;
|
reg rclk = 0;
|
||||||
reg rclk2 = 0;
|
reg rclk2 = 0;
|
||||||
reg addr_reset = 0;
|
reg addr_reset = 0;
|
||||||
reg downloading_reg = 0;
|
reg downloading_reg = 0;
|
||||||
reg uploading_reg = 0;
|
|
||||||
reg reg_do;
|
|
||||||
|
|
||||||
localparam DIO_FILE_TX = 8'h53;
|
localparam DIO_FILE_TX = 8'h53;
|
||||||
localparam DIO_FILE_TX_DAT = 8'h54;
|
localparam DIO_FILE_TX_DAT = 8'h54;
|
||||||
localparam DIO_FILE_INDEX = 8'h55;
|
localparam DIO_FILE_INDEX = 8'h55;
|
||||||
localparam DIO_FILE_INFO = 8'h56;
|
localparam DIO_FILE_INFO = 8'h56;
|
||||||
localparam DIO_FILE_RX = 8'h57;
|
|
||||||
localparam DIO_FILE_RX_DAT = 8'h58;
|
|
||||||
|
|
||||||
assign SPI_DO = reg_do;
|
|
||||||
|
|
||||||
// data_io has its own SPI interface to the io controller
|
// data_io has its own SPI interface to the io controller
|
||||||
always@(negedge SPI_SCK or posedge SPI_SS2) begin : SPI_TRANSMITTER
|
|
||||||
reg [7:0] dout_r;
|
|
||||||
|
|
||||||
if(SPI_SS2) begin
|
|
||||||
reg_do <= 1'bZ;
|
|
||||||
end else begin
|
|
||||||
if (cnt == 15) dout_r <= ioctl_din;
|
|
||||||
reg_do <= dout_r[~cnt[2:0]];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
||||||
reg [6:0] sbuf;
|
reg [6:0] sbuf;
|
||||||
reg [24:0] addr;
|
|
||||||
reg [7:0] cmd;
|
reg [7:0] cmd;
|
||||||
|
reg [3:0] cnt;
|
||||||
reg [5:0] bytecnt;
|
reg [5:0] bytecnt;
|
||||||
|
reg [24:0] addr;
|
||||||
|
|
||||||
if(SPI_SS2) begin
|
if(SPI_SS2) begin
|
||||||
bytecnt <= 0;
|
bytecnt <= 0;
|
||||||
@ -104,10 +84,8 @@ always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
|||||||
// finished command byte
|
// finished command byte
|
||||||
if(cnt == 7) cmd <= {sbuf, SPI_DI};
|
if(cnt == 7) cmd <= {sbuf, SPI_DI};
|
||||||
|
|
||||||
if(cnt == 15) begin
|
|
||||||
case (cmd)
|
|
||||||
// prepare/end transmission
|
// prepare/end transmission
|
||||||
DIO_FILE_TX: begin
|
if((cmd == DIO_FILE_TX) && (cnt == 15)) begin
|
||||||
// prepare
|
// prepare
|
||||||
if(SPI_DI) begin
|
if(SPI_DI) begin
|
||||||
addr_reset <= ~addr_reset;
|
addr_reset <= ~addr_reset;
|
||||||
@ -117,29 +95,17 @@ always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DIO_FILE_RX: begin
|
// command 0x54: UIO_FILE_TX
|
||||||
// prepare
|
if((cmd == DIO_FILE_TX_DAT) && (cnt == 15)) begin
|
||||||
if(SPI_DI) begin
|
|
||||||
addr_reset <= ~addr_reset;
|
|
||||||
uploading_reg <= 1;
|
|
||||||
end else begin
|
|
||||||
uploading_reg <= 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// command 0x57: DIO_FILE_RX_DAT
|
|
||||||
// command 0x54: DIO_FILE_TX_DAT
|
|
||||||
DIO_FILE_RX_DAT,
|
|
||||||
DIO_FILE_TX_DAT: begin
|
|
||||||
data_w <= {sbuf, SPI_DI};
|
data_w <= {sbuf, SPI_DI};
|
||||||
rclk <= ~rclk;
|
rclk <= ~rclk;
|
||||||
end
|
end
|
||||||
|
|
||||||
// expose file (menu) index
|
// expose file (menu) index
|
||||||
DIO_FILE_INDEX: ioctl_index <= {sbuf, SPI_DI};
|
if((cmd == DIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
|
||||||
|
|
||||||
// receiving FAT directory entry (mist-firmware/fat.h - DIRENTRY)
|
// receiving FAT directory entry (mist-firmware/fat.h - DIRENTRY)
|
||||||
DIO_FILE_INFO: begin
|
if((cmd == DIO_FILE_INFO) && (cnt == 15)) begin
|
||||||
bytecnt <= bytecnt + 1'd1;
|
bytecnt <= bytecnt + 1'd1;
|
||||||
case (bytecnt)
|
case (bytecnt)
|
||||||
8'h08: ioctl_fileext[23:16] <= {sbuf, SPI_DI};
|
8'h08: ioctl_fileext[23:16] <= {sbuf, SPI_DI};
|
||||||
@ -151,8 +117,6 @@ always@(posedge SPI_SCK, posedge SPI_SS2) begin : SPI_RECEIVER
|
|||||||
8'h1F: ioctl_filesize[31:24] <= {sbuf, SPI_DI};
|
8'h1F: ioctl_filesize[31:24] <= {sbuf, SPI_DI};
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -198,7 +162,7 @@ always@(posedge clk_sys) begin : DATA_OUT
|
|||||||
reg rclk2D, rclk2D2;
|
reg rclk2D, rclk2D2;
|
||||||
reg addr_resetD, addr_resetD2;
|
reg addr_resetD, addr_resetD2;
|
||||||
|
|
||||||
reg wr_int, wr_int_direct, rd_int;
|
reg wr_int, wr_int_direct;
|
||||||
reg [24:0] addr;
|
reg [24:0] addr;
|
||||||
reg [31:0] filepos;
|
reg [31:0] filepos;
|
||||||
|
|
||||||
@ -215,13 +179,7 @@ always@(posedge clk_sys) begin : DATA_OUT
|
|||||||
wr_int_direct <= 0;
|
wr_int_direct <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (!uploading_reg) begin
|
|
||||||
ioctl_upload <= 0;
|
|
||||||
rd_int <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (~clkref_n) begin
|
if (~clkref_n) begin
|
||||||
rd_int <= 0;
|
|
||||||
wr_int <= 0;
|
wr_int <= 0;
|
||||||
wr_int_direct <= 0;
|
wr_int_direct <= 0;
|
||||||
if (wr_int || wr_int_direct) begin
|
if (wr_int || wr_int_direct) begin
|
||||||
@ -230,26 +188,17 @@ always@(posedge clk_sys) begin : DATA_OUT
|
|||||||
addr <= addr + 1'd1;
|
addr <= addr + 1'd1;
|
||||||
ioctl_addr <= addr;
|
ioctl_addr <= addr;
|
||||||
end
|
end
|
||||||
if (rd_int) begin
|
|
||||||
ioctl_addr <= ioctl_addr + 1'd1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// detect transfer start from the SPI receiver
|
// detect transfer start from the SPI receiver
|
||||||
if(addr_resetD ^ addr_resetD2) begin
|
if(addr_resetD ^ addr_resetD2) begin
|
||||||
addr <= START_ADDR;
|
addr <= START_ADDR;
|
||||||
ioctl_addr <= START_ADDR;
|
|
||||||
filepos <= 0;
|
filepos <= 0;
|
||||||
ioctl_download <= downloading_reg;
|
ioctl_download <= 1;
|
||||||
ioctl_upload <= uploading_reg;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// detect new byte from the SPI receiver
|
// detect new byte from the SPI receiver
|
||||||
if (rclkD ^ rclkD2) begin
|
if (rclkD ^ rclkD2) wr_int <= 1;
|
||||||
wr_int <= downloading_reg;
|
|
||||||
rd_int <= uploading_reg;
|
|
||||||
end
|
|
||||||
// direct transfer receiver
|
|
||||||
if (rclk2D ^ rclk2D2 && filepos != ioctl_filesize) begin
|
if (rclk2D ^ rclk2D2 && filepos != ioctl_filesize) begin
|
||||||
filepos <= filepos + 1'd1;
|
filepos <= filepos + 1'd1;
|
||||||
wr_int_direct <= 1;
|
wr_int_direct <= 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user