1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-05 07:34:41 +00:00

C16: import mist-modules, use common components

This commit is contained in:
Gyorgy Szombathelyi
2020-02-17 21:12:38 +01:00
parent 562d478253
commit 37fb0aba26
10 changed files with 104 additions and 2432 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "mist-modules"]
path = mist-modules
url = https://github.com/mist-devel/mist-modules.git

View File

@@ -41,7 +41,7 @@
# ========================
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "21:40:24 MAY 17, 2014"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name SMART_RECOMPILE ON
@@ -348,11 +348,7 @@ set_global_assignment -name VHDL_FILE tap_fifo.vhd
set_global_assignment -name VHDL_FILE c1530.vhd
set_global_assignment -name VHDL_FILE gen_ram.vhd
set_global_assignment -name VERILOG_FILE sigma_delta_dac.v
set_global_assignment -name VERILOG_FILE data_io.v
set_global_assignment -name VERILOG_FILE sdram.v
set_global_assignment -name VERILOG_FILE osd.v
set_global_assignment -name VERILOG_FILE scandoubler.v
set_global_assignment -name VERILOG_FILE user_io.v
set_global_assignment -name VERILOG_FILE ted.v
set_global_assignment -name VERILOG_FILE mos8501.v
set_global_assignment -name VERILOG_FILE mos6529.v
@@ -363,6 +359,7 @@ set_global_assignment -name VERILOG_FILE c16_keymatrix.v
set_global_assignment -name VERILOG_FILE c16.v
set_global_assignment -name VERILOG_FILE ps2receiver.v
set_global_assignment -name VERILOG_FILE basic_rom.v
set_global_assignment -name QIP_FILE "../../mist-modules/mist.qip"
set_global_assignment -name VHDL_FILE c1541/gcr_floppy.vhd
set_global_assignment -name VHDL_FILE c1541/spram.vhd
set_global_assignment -name VHDL_FILE c1541/gen_rom.vhd
@@ -374,8 +371,6 @@ set_global_assignment -name VHDL_FILE t65/T65_Pack.vhd
set_global_assignment -name VHDL_FILE t65/T65_MCode.vhd
set_global_assignment -name VHDL_FILE t65/T65_ALU.vhd
set_global_assignment -name VHDL_FILE t65/T65.vhd
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
set_global_assignment -name SYSTEMVERILOG_FILE rgb2ypbpr.sv
set_global_assignment -name QIP_FILE pll_c1541.qip
set_global_assignment -name QIP_FILE pll_c16.qip
set_global_assignment -name QIP_FILE rom_reconfig_pal.qip

View File

@@ -77,14 +77,14 @@ parameter CONF_STR = {
"F,ROM,Load Kernal;",
"T6,Play/Stop tape;",
"O7,Tape sound,Off,On;",
"O2,Scanlines,Off,On;",
"O12,Scanlines,Off,25%,50%,75%;",
"O3,Joysticks,Normal,Swapped;",
"O4,Memory,64k,16k;",
"O89,SID,Off,6581,8580;",
"T5,Reset;"
};
parameter CONF_STR_LEN = 11+17+18+18+21+20+28+18+22+9;
parameter CONF_STR_LEN = 11+17+18+18+21+30+28+18+22+9;
localparam ROM_MEM_START = 25'h10000;
localparam TAP_MEM_START = 25'h20000;
@@ -104,7 +104,8 @@ assign UART_TX = ~cass_motor;
wire [31:0] status;
wire tv15khz;
wire ypbpr;
wire scanlines = status[2];
wire no_csync;
wire [1:0] scanlines = status[2:1];
wire joystick_swap = status[3];
wire memory_16k = status[4];
wire osd_reset = status[5];
@@ -274,58 +275,54 @@ wire img_mounted;
wire [8:0] sd_buff_addr;
// include user_io module for arm controller communication
user_io #(.STRLEN(CONF_STR_LEN)) user_io (
.conf_str ( CONF_STR ),
user_io #(.STRLEN(CONF_STR_LEN)) user_io (
.conf_str ( CONF_STR ),
.clk_sys ( clk28 ),
.clk_sd ( clk32 ),
.clk_sys ( clk28 ),
.clk_sd ( clk32 ),
.SPI_CLK ( SPI_SCK ),
.SPI_SS_IO ( CONF_DATA0 ),
.SPI_MISO ( SPI_DO ),
.SPI_MOSI ( SPI_DI ),
.SPI_CLK ( SPI_SCK ),
.SPI_SS_IO ( CONF_DATA0 ),
.SPI_MISO ( SPI_DO ),
.SPI_MOSI ( SPI_DI ),
.scandoubler_disable ( tv15khz ),
.ypbpr ( ypbpr ),
.buttons ( buttons ),
.scandoubler_disable ( tv15khz ),
.ypbpr ( ypbpr ),
.no_csync ( no_csync ),
.buttons ( buttons ),
.joystick_0 ( js0 ),
.joystick_1 ( js1 ),
.joystick_0 ( js0 ),
.joystick_1 ( js1 ),
// ps2 interface
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data ),
.ps2_mouse_clk ( ps2_mouse_clk ),
.ps2_mouse_data ( ps2_mouse_data ),
// ps2 interface
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data ),
.ps2_mouse_clk ( ps2_mouse_clk ),
.ps2_mouse_data ( ps2_mouse_data ),
.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 ),
.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 ),
.status ( status )
.status ( status )
);
wire sd_cs;
wire sd_dat;
wire sd_cmd;
wire sd_clk;
// ---------------------------------------------------------------------------------
// ------------------------------ prg memory injection -----------------------------
// ---------------------------------------------------------------------------------
wire ioctl_wr;
wire [15:0] ioctl_addr;
wire [24:0] ioctl_addr;
wire [7:0] ioctl_data;
wire [7:0] ioctl_index;
wire ioctl_downloading;
@@ -337,18 +334,18 @@ wire tap_download = ioctl_downloading && (ioctl_index == 8'h41);
wire c16_wait = rom_download | prg_download;
data_io data_io (
// SPI interface
.sck ( SPI_SCK ),
.ss ( SPI_SS2 ),
.sdi ( SPI_DI ),
// ram interface
.downloading ( ioctl_downloading ),
.index ( ioctl_index ),
.clk ( clk28 ),
.wr ( ioctl_wr ),
.a ( ioctl_addr ),
.d ( ioctl_data )
.clk_sys ( clk28 ),
// SPI interface
.SPI_SCK ( SPI_SCK ),
.SPI_SS2 ( SPI_SS2 ),
.SPI_DI ( SPI_DI ),
// ram interface
.ioctl_download ( ioctl_downloading ),
.ioctl_index ( ioctl_index ),
.ioctl_wr ( ioctl_wr ),
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_data )
);
// magic zero page shadow registers to allow the injector to set the
@@ -429,18 +426,18 @@ always @(posedge clk28) begin
// data io has a byte for us
if(ioctl_wr) begin
if (prg_download) begin
if(ioctl_addr == 16'h0000) ioctl_sdram_addr[7:0] <= ioctl_data;
else if (ioctl_addr == 16'h0001) ioctl_sdram_addr[24:8] <= { 9'b0, ioctl_data };
if(ioctl_addr == 0) ioctl_sdram_addr[7:0] <= ioctl_data;
else if (ioctl_addr == 25'h1) ioctl_sdram_addr[24:8] <= { 9'b0, ioctl_data };
else
// io controller sent a new byte. Store it until it can be
// saved in RAM
ioctl_ram_wr <= 1'b1;
end else if (tap_download) begin
if(ioctl_addr == 16'h0000) ioctl_sdram_addr <= TAP_MEM_START;
if(ioctl_addr == 0) ioctl_sdram_addr <= TAP_MEM_START;
ioctl_ram_wr <= 1'b1;
end else if (rom_download) begin
if((ioctl_index == 8'h0 && ioctl_addr == 16'h4000) || (ioctl_index == 8'h3 && ioctl_addr == 16'h0000)) ioctl_sdram_addr <= ROM_MEM_START;
if((ioctl_index == 8'h0 && ioctl_addr[15:14]) || ioctl_index == 8'h3) ioctl_ram_wr <= 1'b1;
if((ioctl_index == 8'h0 && ioctl_addr == 25'h4000) || (ioctl_index == 8'h3 && ioctl_addr == 0)) ioctl_sdram_addr <= ROM_MEM_START;
if((ioctl_index == 8'h0 && ioctl_addr[16:14] != 0) || ioctl_index == 8'h3) ioctl_ram_wr <= 1'b1;
end
end
@@ -521,90 +518,54 @@ c1530 c1530
);
// ---------------------------------------------------------------------------------
// ------------------------------ the on screen display ----------------------------
// ---------------------------------- video output ---------------------------------
// ---------------------------------------------------------------------------------
// in 15khz mode feed the c16 video directly into the OSD,
// bypassing the scan doubler
wire [5:0] osd_r_in = tv15khz?{c16_r, 2'b00}:video_r;
wire [5:0] osd_g_in = tv15khz?{c16_g, 2'b00}:video_g;
wire [5:0] osd_b_in = tv15khz?{c16_b, 2'b00}:video_b;
wire osd_hs_in = tv15khz?c16_hs:video_hs;
wire osd_vs_in = tv15khz?!c16_vs:video_vs;
wire hs, vs;
wire osd_clk = tv15khz?clk7:clk14;
mist_video #(.COLOR_DEPTH(4), .OSD_COLOR(3'd5), .SD_HCNT_WIDTH(10)) mist_video (
.clk_sys ( clk28 ),
wire [5:0] red, green, blue;
// OSD SPI interface
.SPI_SCK ( SPI_SCK ),
.SPI_SS3 ( SPI_SS3 ),
.SPI_DI ( SPI_DI ),
// include the on screen display
osd #(10'd11,10'd0,3'd5) osd (
.clk_sys ( clk28 ),
.ce_pix ( osd_clk ),
// scanlines (00-none 01-25% 10-50% 11-75%)
.scanlines ( scanlines ),
// spi for OSD
.sdi ( SPI_DI ),
.sck ( SPI_SCK ),
.ss ( SPI_SS3 ),
// non-scandoubled pixel clock divider 0 - clk_sys/4, 1 - clk_sys/2
.ce_divider ( 1'b0 ),
.red_in ( osd_r_in ),
.green_in ( osd_g_in ),
.blue_in ( osd_b_in ),
.hs_in ( osd_hs_in ),
.vs_in ( osd_vs_in ),
// 0 = HVSync 31KHz, 1 = CSync 15KHz
.scandoubler_disable ( tv15khz ),
// disable csync without scandoubler
.no_csync ( no_csync ),
// YPbPr always uses composite sync
.ypbpr ( ypbpr ),
// Rotate OSD [0] - rotate [1] - left or right
.rotate ( 2'b00 ),
// composite-like blending
.blend ( 1'b0 ),
.red_out ( red ),
.green_out ( green ),
.blue_out ( blue )
// video in
.R ( c16_r ),
.G ( c16_g ),
.B ( c16_b ),
.HSync ( c16_hs ),
.VSync ( ~c16_vs ),
// MiST video output signals
.VGA_R ( VGA_R ),
.VGA_G ( VGA_G ),
.VGA_B ( VGA_B ),
.VGA_VS ( vs ),
.VGA_HS ( hs )
);
wire [5:0] y, pb, pr;
rgb2ypbpr rgb2ypbpr (
.red ( red ),
.green ( green ),
.blue ( blue ),
.y ( y ),
.pb ( pb ),
.pr ( pr )
);
assign VGA_R = ypbpr ? pr : red;
assign VGA_G = ypbpr ? y : green;
assign VGA_B = ypbpr ? pb : blue;
// in 15khz tv mode directly use the c16's composite sync. Otherwise the VGA
// output is driven from the sync signals generated by the scan doubler. In
// 15khz mode the VS signal is used as the RGB detect signal on the SCART
// connector and thus needs to be driven to 1
assign VGA_HS = tv15khz ? c16_cs:(ypbpr ? ~(video_hs ^ video_vs) : video_hs);
assign VGA_VS = (tv15khz || ypbpr)?1'b1:video_vs;
wire video_hs, video_vs;
wire [5:0] video_r;
wire [5:0] video_g;
wire [5:0] video_b;
scandoubler scandoubler (
// system interface
.clk_sys ( clk28 ),
// scanlines (00-none 01-25% 10-50% 11-75%)
.scanlines ( scanlines?2'b10:2'b00 ),
// shifter video interface
.hs_in ( c16_hs ),
.vs_in ( !c16_vs ),
.r_in ( c16_r ),
.g_in ( c16_g ),
.b_in ( c16_b ),
// output interface
.hs_out ( video_hs ),
.vs_out ( video_vs ),
.r_out ( video_r ),
.g_out ( video_g ),
.b_out ( video_b )
);
// Use TED generated csync @15kHz
assign VGA_HS = (~no_csync & tv15khz & ~ypbpr) ? c16_cs : hs;
assign VGA_VS = (~no_csync & tv15khz & ~ypbpr) ? 1'b1 : vs;
// ---------------------------------------------------------------------------------
// ------------------------------------ c16 core -----------------------------------
@@ -631,14 +592,14 @@ reg [13:0] rom_dl_addr;
wire ioctl_rom_wr = rom_download && ioctl_wr;
always @(negedge clk28) begin
reg last_ioctl_rom_wr;
reg last_ioctl_rom_wr;
last_ioctl_rom_wr <= ioctl_rom_wr;
if(ioctl_rom_wr && !last_ioctl_rom_wr) begin
rom_dl_data <= ioctl_data;
rom_dl_addr <= ioctl_addr[13:0];
c1541_dl_wr <= !ioctl_addr[15:14] && ioctl_index == 5'd0;
kernal_dl_wr <= ioctl_addr[15:14] == 2'd1 || ioctl_index == 5'd3;
basic_dl_wr <= ioctl_addr[15:14] == 2'd2 && ioctl_index == 5'd0;
c1541_dl_wr <= ioctl_addr[16:14] == 3'd0 && ioctl_index == 8'h0;
kernal_dl_wr <= ioctl_addr[16:14] == 3'd1 || ioctl_index == 8'h3;
basic_dl_wr <= ioctl_addr[16:14] == 3'd2 && ioctl_index == 8'h0;
end else
{ kernal_dl_wr, basic_dl_wr, c1541_dl_wr } <= 0;
end
@@ -724,19 +685,6 @@ C16 #(.INTERNAL_ROM(0)) c16 (
wire pll_locked = pll_c1541_locked && pll_c16_locked;
wire ntsc = ~c16_pal;
// tv15hkz has quarter the pixel rate, so we need a 7mhz clock for the OSD
reg clk7;
reg clk14;
always @(posedge clk28) begin
reg [1:0] counter;
counter <= counter + 1'd1;
clk7 <= !counter;
clk14 <= !counter[0];
end
// A PLL to derive the system clock from the MiSTs 27MHz
wire pll_c1541_locked, clk32;
pll_c1541 pll_c1541 (

View File

@@ -1,127 +0,0 @@
//
// data_io.v
//
// io controller writable ram 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 (
// io controller spi interface
input sck,
input ss,
input sdi,
output downloading, // signal indicating an active download
output [15:0] size, // number of bytes in input buffer
output reg [7:0] index, // menu index used to upload the file
// external ram interface
input clk,
output reg wr,
output reg [15:0] a,
output [7:0] d
);
assign d = data;
parameter START_ADDR = 16'h0000;
assign size = addr;
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg [6:0] sbuf;
reg [7:0] cmd /* synthesis noprune */;
reg [7:0] data /* synthesis noprune */;
reg [4:0] cnt /* synthesis noprune */;
reg [15:0] addr /* synthesis noprune */;
reg rclk /* synthesis noprune */;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
localparam UIO_FILE_INFO = 8'h56;
assign downloading = downloading_reg;
reg downloading_reg = 1'b0;
// data_io has its own SPI interface to the io controller
always@(posedge sck, posedge ss) begin
if(ss == 1'b1)
cnt <= 5'd0;
else begin
rclk <= 1'b0;
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 15)
sbuf <= { sbuf[5:0], sdi};
// increase target address after write
if(rclk && ~&addr)
addr <= addr + 16'd1;
// count 0-7 8-15 8-15 ...
if(cnt < 15) cnt <= cnt + 4'd1;
else cnt <= 4'd8;
// finished command byte
if(cnt == 7)
cmd <= {sbuf, sdi};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(sdi) begin
addr <= START_ADDR;
downloading_reg <= 1'b1;
end else
downloading_reg <= 1'b0;
end
// command 0x54: UIO_FILE_TX
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
data <= {sbuf, sdi};
rclk <= 1'b1;
a <= addr;
end
// expose file (menu) index
if((cmd == UIO_FILE_INDEX) && (cnt == 15))
index <= {sbuf[6:0], sdi};
end
end
reg rclkD, rclkD2;
always@(posedge clk) begin
// bring rclk from spi clock domain into c64 clock domain
rclkD <= rclk;
rclkD2 <= rclkD;
wr <= 1'b0;
if(rclkD && !rclkD2)
wr <= 1'b1;
end
endmodule

View File

@@ -1,208 +0,0 @@
//
// osd.v
//
// A simple OSD implementation. Can be hooked up between a cores
// VGA output and the physical VGA pins
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 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 osd (
// OSDs pixel clock, should be synchronous to cores pixel clock to
// avoid jitter.
input clk_sys,
input ce_pix,
// SPI interface
input sck,
input ss,
input sdi,
// VGA signals coming from core
input [5:0] red_in,
input [5:0] green_in,
input [5:0] blue_in,
input hs_in,
input vs_in,
// VGA signals going to video connector
output [5:0] red_out,
output [5:0] green_out,
output [5:0] blue_out,
output hs_out,
output vs_out
);
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter OSD_COLOR = 3'd0;
localparam OSD_WIDTH = 10'd256;
localparam OSD_HEIGHT = 10'd128;
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg [7:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg [10:0] bcnt;
reg osd_enable;
reg [7:0] osd_buffer [2047:0]; // the OSD buffer itself
// the OSD has its own SPI interface to the io controller
always@(posedge sck, posedge ss) begin
if(ss == 1'b1) begin
cnt <= 5'd0;
bcnt <= 11'd0;
end else begin
sbuf <= { sbuf[6:0], sdi};
// 0:7 is command, rest payload
if(cnt < 15)
cnt <= cnt + 4'd1;
else
cnt <= 4'd8;
if(cnt == 7) begin
cmd <= {sbuf[6:0], sdi};
// lower three command bits are line address
bcnt <= { sbuf[1:0], sdi, 8'h00};
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
if(sbuf[6:3] == 4'b0100)
osd_enable <= sdi;
end
// command 0x20: OSDCMDWRITE
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
osd_buffer[bcnt] <= {sbuf[6:0], sdi};
bcnt <= bcnt + 11'd1;
end
end
end
// *********************************************************************************
// video timing and sync polarity anaylsis
// *********************************************************************************
// horizontal counter
reg [9:0] h_cnt;
reg [9:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [9:0] h_dsp_width = hs_pol?hs_low:hs_high;
wire [9:0] h_dsp_ctr = { 1'b0, h_dsp_width[9:1] };
always @(posedge clk_sys) begin
reg hsD;
if (ce_pix) begin
hsD <= hs_in;
// falling edge of hs_in
if(!hs_in && hsD) begin
h_cnt <= 10'd0;
hs_high <= h_cnt;
end
// rising edge of hs_in
else if(hs_in && !hsD) begin
h_cnt <= 10'd0;
hs_low <= h_cnt;
end
else
h_cnt <= h_cnt + 10'd1;
end
end
// vertical counter
reg [9:0] v_cnt;
reg [9:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [9:0] v_dsp_height = vs_pol?vs_low:vs_high;
wire [9:0] v_dsp_ctr = { 1'b0, v_dsp_height[9:1] };
wire doublescan = (v_dsp_height>350);
always @(posedge clk_sys) begin
reg hsD, vsD;
hsD <= hs_in;
if (~hsD & hs_in) begin
vsD <= vs_in;
// falling edge of vs_in
if(!vs_in && vsD) begin
v_cnt <= 10'd0;
vs_high <= v_cnt;
end
// rising edge of vs_in
else if(vs_in && !vsD) begin
v_cnt <= 10'd0;
vs_low <= v_cnt;
end
else
v_cnt <= v_cnt + 10'd1;
end
end
// area in which OSD is being displayed
wire [9:0] h_osd_start = h_dsp_ctr + OSD_X_OFFSET - (OSD_WIDTH >> 1);
wire [9:0] h_osd_end = h_dsp_ctr + OSD_X_OFFSET + (OSD_WIDTH >> 1) - 1'd1;
wire [9:0] v_osd_start = v_dsp_ctr + OSD_Y_OFFSET - (doublescan ? OSD_HEIGHT : OSD_HEIGHT >> 1);
wire [9:0] v_osd_end = v_dsp_ctr + OSD_Y_OFFSET + (doublescan ? OSD_HEIGHT : OSD_HEIGHT >> 1) - 1'd1;
reg h_osd_active, v_osd_active;
always @(posedge clk_sys) begin
if(hs_in != hs_pol) begin
if(h_cnt == h_osd_start) h_osd_active <= 1'b1;
if(h_cnt == h_osd_end) h_osd_active <= 1'b0;
end
if(vs_in != vs_pol) begin
if(v_cnt == v_osd_start) v_osd_active <= 1'b1;
if(v_cnt == v_osd_end) v_osd_active <= 1'b0;
end
end
wire osd_de = osd_enable && h_osd_active && v_osd_active;
wire [9:0] osd_hcnt = h_cnt - h_osd_start + 7'd1; // one pixel offset for osd_byte register
wire [9:0] osd_vcnt = v_cnt - v_osd_start;
reg [7:0] osd_byte;
always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}];
wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]];
wire [2:0] osd_color = OSD_COLOR;
assign red_out = !osd_de?red_in: {osd_pixel, osd_pixel, osd_color[2], red_in[5:3] };
assign green_out = !osd_de?green_in:{osd_pixel, osd_pixel, osd_color[1], green_in[5:3]};
assign blue_out = !osd_de?blue_in: {osd_pixel, osd_pixel, osd_color[0], blue_in[5:3] };
assign hs_out = hs_in;
assign vs_out = vs_in;
endmodule

View File

@@ -1,55 +0,0 @@
module rgb2ypbpr (
input [5:0] red,
input [5:0] green,
input [5:0] blue,
output [5:0] y,
output [5:0] pb,
output [5:0] pr
);
wire [5:0] yuv_full[225] = '{
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,
6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6,
6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8,
6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11,
6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13,
6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15,
6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17,
6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20,
6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22,
6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24,
6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27,
6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29,
6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31,
6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33,
6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36,
6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38,
6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40,
6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42,
6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45,
6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47,
6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49,
6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52,
6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54,
6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56,
6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58,
6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61,
6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63,
6'd63
};
wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0});
wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0});
wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0});
wire [7:0] y_i = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8];
wire [7:0] pb_i = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8];
wire [7:0] pr_i = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8];
assign pr = yuv_full[pr_i - 8'd16];
assign y = yuv_full[y_i - 8'd16];
assign pb = yuv_full[pb_i - 8'd16];
endmodule

View File

@@ -1,177 +0,0 @@
//
// scandoubler.v
//
// Copyright (c) 2015 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/>.
// TODO: Delay vsync one line
module scandoubler
(
// system interface
input clk_sys,
// scanlines (00-none 01-25% 10-50% 11-75%)
input [1:0] scanlines,
// shifter video interface
input hs_in,
input vs_in,
input [3:0] r_in,
input [3:0] g_in,
input [3:0] b_in,
// output interface
output reg hs_out,
output reg vs_out,
output reg [5:0] r_out,
output reg [5:0] g_out,
output reg [5:0] b_out
);
// try to detect changes in input signal and lock input clock gate
// it
reg last_hs_in;
reg [1:0] i_div;
wire ce_x1 = (i_div == 2'b01);
wire ce_x2 = i_div[0];
always @(posedge clk_sys) begin
if(last_hs_in != hs_in) begin
i_div <= 2'b00;
last_hs_in <= hs_in;
end else begin
i_div <= i_div + 2'd1;
end
end
// --------------------- create output signals -----------------
// latch everything once more to make it glitch free and apply scanline effect
reg scanline;
always @(posedge clk_sys) begin
if(ce_x2) begin
hs_out <= hs_sd;
vs_out <= vs_in;
// reset scanlines at every new screen
if(vs_out != vs_in) scanline <= 0;
// toggle scanlines at begin of every hsync
if(hs_out && !hs_sd) scanline <= !scanline;
// if no scanlines or not a scanline
if(!scanline || !scanlines) begin
r_out <= { sd_out[11:8], 2'b00 };
g_out <= { sd_out[7:4], 2'b00 };
b_out <= { sd_out[3:0], 2'b00 };
end else begin
case(scanlines)
1: begin // reduce 25% = 1/2 + 1/4
r_out <= {1'b0, sd_out[11:8], 1'b0} + {2'b00, sd_out[11:8]};
g_out <= {1'b0, sd_out[7:4], 1'b0} + {2'b00, sd_out[7:4] };
b_out <= {1'b0, sd_out[3:0], 1'b0} + {2'b00, sd_out[3:0] };
end
2: begin // reduce 50% = 1/2
r_out <= {1'b0, sd_out[11:8], 1'b0};
g_out <= {1'b0, sd_out[7:4], 1'b0};
b_out <= {1'b0, sd_out[3:0], 1'b0};
end
3: begin // reduce 75% = 1/4
r_out <= {2'b00, sd_out[11:8]};
g_out <= {2'b00, sd_out[7:4]};
b_out <= {2'b00, sd_out[3:0]};
end
endcase
end
end
end
// scan doubler output register
reg [11:0] sd_out;
// ==================================================================
// ======================== the line buffers ========================
// ==================================================================
// 2 lines of 512 pixels 3*4 bit RGB
(* ramstyle = "no_rw_check" *) reg [11:0] sd_buffer[1023:0];
// use alternating sd_buffers when storing/reading data
reg line_toggle;
// total hsync time (in 16MHz cycles), hs_total reaches 1024
reg [8:0] hs_max;
reg [8:0] hs_rise;
reg [8:0] hcnt;
always @(posedge clk_sys) begin
reg hsD, vsD;
if(ce_x1) begin
hsD <= hs_in;
// falling edge of hsync indicates start of line
if(hsD && !hs_in) begin
hs_max <= hcnt;
hcnt <= 9'd0;
end else begin
hcnt <= hcnt + 9'd1;
end
// save position of rising edge
if(!hsD && hs_in) hs_rise <= hcnt;
vsD <= vs_in;
if(vsD != vs_in) line_toggle <= 0;
// begin of incoming hsync
if(hsD && !hs_in) line_toggle <= !line_toggle;
sd_buffer[{line_toggle, hcnt}] <= {r_in, g_in, b_in};
end
end
// ==================================================================
// ==================== output timing generation ====================
// ==================================================================
reg [8:0] sd_hcnt;
reg hs_sd;
// timing generation runs 32 MHz (twice the input signal analysis speed)
always @(posedge clk_sys) begin
reg hsD;
if(ce_x2) begin
hsD <= hs_in;
// output counter synchronous to input and at twice the rate
sd_hcnt <= sd_hcnt + 9'd1;
if(hsD && !hs_in) sd_hcnt <= hs_max;
if(sd_hcnt == hs_max) sd_hcnt <= 0;
// replicate horizontal sync at twice the speed
if(sd_hcnt == hs_max) hs_sd <= 0;
if(sd_hcnt == hs_rise) hs_sd <= 1;
// read data from line sd_buffer
sd_out <= sd_buffer[{~line_toggle, sd_hcnt}];
end
end
endmodule

File diff suppressed because one or more lines are too long

View File

@@ -1,522 +0,0 @@
//
// user_io.v
//
// user_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/>.
//
// parameter STRLEN and the actual length of conf_str have to match
module user_io #(parameter STRLEN=0, parameter PS2DIV=100) (
input [(8*STRLEN)-1:0] conf_str,
input clk_sys, // clock for system-related messages (kbd, joy, etc...)
input clk_sd, // clock for SD-card related messages
input SPI_CLK,
input SPI_SS_IO,
output reg SPI_MISO,
input SPI_MOSI,
output reg [31:0] joystick_0,
output reg [31:0] joystick_1,
output reg [31:0] joystick_2,
output reg [31:0] joystick_3,
output reg [31:0] joystick_4,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoubler_disable,
output ypbpr,
output reg [31:0] status,
// connection to sd card emulation
input [31:0] sd_lba,
input sd_rd,
input 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 img_mounted, //rising edge if a new image is mounted
output reg [31:0] img_size, // size of image in bytes
// ps2 keyboard emulation
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
// serial com port
input [7:0] serial_data,
input serial_strobe
);
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [9:0] byte_cnt; // counts bytes
reg [7:0] but_sw;
reg [2:0] stick_idx;
assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign ypbpr = but_sw[5];
// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
// command byte read by the io controller
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
wire spi_sck = SPI_CLK;
// ---------------- PS2 ---------------------
// 8 byte fifos to store ps2 bytes
localparam PS2_FIFO_BITS = 3;
reg ps2_clk;
always @(negedge clk_sys) begin
integer cnt;
cnt <= cnt + 1'd1;
if(cnt == PS2DIV) begin
ps2_clk <= ~ps2_clk;
cnt <= 0;
end
end
// keyboard
reg [7:0] ps2_kbd_fifo [(2**PS2_FIFO_BITS)-1:0];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;
assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_kbd_r_inc;
always@(posedge clk_sys) begin
reg ps2_clkD;
ps2_clkD <= ps2_clk;
if (~ps2_clkD & ps2_clk) begin
ps2_kbd_r_inc <= 1'b0;
if(ps2_kbd_r_inc)
ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;
// transmitter is idle?
if(ps2_kbd_tx_state == 0) begin
// data in fifo present?
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
// load tx register from fifo
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
ps2_kbd_r_inc <= 1'b1;
// reset parity
ps2_kbd_parity <= 1'b1;
// start transmitter
ps2_kbd_tx_state <= 4'd1;
// put start bit on data line
ps2_kbd_data <= 1'b0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
if(ps2_kbd_tx_byte[0])
ps2_kbd_parity <= !ps2_kbd_parity;
end
// transmission of parity
if(ps2_kbd_tx_state == 9)
ps2_kbd_data <= ps2_kbd_parity;
// transmission of stop bit
if(ps2_kbd_tx_state == 10)
ps2_kbd_data <= 1'b1; // stop bit is 1
// advance state machine
if(ps2_kbd_tx_state < 11)
ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1;
else
ps2_kbd_tx_state <= 4'd0;
end
end
end
// mouse
reg [7:0] ps2_mouse_fifo [(2**PS2_FIFO_BITS)-1:0];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;
assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_mouse_r_inc;
always@(posedge clk_sys) begin
reg ps2_clkD;
ps2_clkD <= ps2_clk;
if (~ps2_clkD & ps2_clk) begin
ps2_mouse_r_inc <= 1'b0;
if(ps2_mouse_r_inc)
ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;
// transmitter is idle?
if(ps2_mouse_tx_state == 0) begin
// data in fifo present?
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
// load tx register from fifo
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
ps2_mouse_r_inc <= 1'b1;
// reset parity
ps2_mouse_parity <= 1'b1;
// start transmitter
ps2_mouse_tx_state <= 4'd1;
// put start bit on data line
ps2_mouse_data <= 1'b0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
if(ps2_mouse_tx_byte[0])
ps2_mouse_parity <= !ps2_mouse_parity;
end
// transmission of parity
if(ps2_mouse_tx_state == 9)
ps2_mouse_data <= ps2_mouse_parity;
// transmission of stop bit
if(ps2_mouse_tx_state == 10)
ps2_mouse_data <= 1'b1; // stop bit is 1
// advance state machine
if(ps2_mouse_tx_state < 11)
ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1;
else
ps2_mouse_tx_state <= 4'd0;
end
end
end
// fifo to receive serial data from core to be forwarded to io controller
// 16 byte fifo to store serial bytes
localparam SERIAL_OUT_FIFO_BITS = 6;
reg [7:0] serial_out_fifo [(2**SERIAL_OUT_FIFO_BITS)-1:0];
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_wptr;
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_rptr;
wire serial_out_data_available = serial_out_wptr != serial_out_rptr;
wire [7:0] serial_out_byte = serial_out_fifo[serial_out_rptr] /* synthesis keep */;
wire [7:0] serial_out_status = { 7'b1000000, serial_out_data_available};
// status[0] is reset signal from io controller and is thus used to flush
// the fifo
always @(posedge serial_strobe or posedge status[0]) begin
if(status[0] == 1) begin
serial_out_wptr <= 0;
end else begin
serial_out_fifo[serial_out_wptr] <= serial_data;
serial_out_wptr <= serial_out_wptr + 1'd1;
end
end
always@(negedge spi_sck or posedge status[0]) begin
if(status[0] == 1) begin
serial_out_rptr <= 0;
end else begin
if((byte_cnt != 0) && (cmd == 8'h1b)) begin
// read last bit -> advance read pointer
if((bit_cnt == 7) && !byte_cnt[0] && serial_out_data_available)
serial_out_rptr <= serial_out_rptr + 1'd1;
end
end
end
// SPI bit and byte counters
always@(posedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
bit_cnt <= 0;
byte_cnt <= 0;
end else begin
if((bit_cnt == 7)&&(~&byte_cnt))
byte_cnt <= byte_cnt + 8'd1;
bit_cnt <= bit_cnt + 1'd1;
end
end
// SPI transmitter FPGA -> IO
reg [7:0] spi_byte_out;
always@(negedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
SPI_MISO <= 1'bZ;
end else begin
SPI_MISO <= spi_byte_out[~bit_cnt];
end
end
always@(posedge spi_sck or posedge SPI_SS_IO) begin
reg [31:0] sd_lba_r;
if(SPI_SS_IO == 1) begin
spi_byte_out <= core_type;
end else begin
// read the command byte to choose the response
if(bit_cnt == 7) begin
if(!byte_cnt) cmd <= {sbuf, SPI_MOSI};
spi_byte_out <= 0;
case({(!byte_cnt) ? {sbuf, SPI_MOSI} : cmd})
// reading config string
8'h14: if(byte_cnt < STRLEN) spi_byte_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8];
// reading sd card status
8'h16: if(byte_cnt == 0) begin
spi_byte_out <= sd_cmd;
sd_lba_r <= sd_lba;
end
else if(byte_cnt < 5) spi_byte_out <= sd_lba_r[(4-byte_cnt)<<3 +:8];
// reading sd card write data
8'h18: spi_byte_out <= sd_din;
8'h1b:
// send alternating flag byte and data
if(byte_cnt[0]) spi_byte_out <= serial_out_status;
else spi_byte_out <= serial_out_byte;
endcase
end
end
end
// SPI receiver IO -> FPGA
reg spi_receiver_strobe_r = 0;
reg spi_transfer_end_r = 1;
reg [7:0] spi_byte_in;
// Read at spi_sck clock domain, assemble bytes for transferring to clk_sys
always@(posedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
spi_transfer_end_r <= 1;
end else begin
spi_transfer_end_r <= 0;
if(bit_cnt != 7)
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
// finished reading a byte, prepare to transfer to clk_sys
if(bit_cnt == 7) begin
spi_byte_in <= { sbuf, SPI_MOSI};
spi_receiver_strobe_r <= ~spi_receiver_strobe_r;
end
end
end
// Process bytes from SPI at the clk_sys domain
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 [7:0] abyte_cnt; // counts bytes
//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 <= 8'd0;
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;
end else begin
case(acmd)
// buttons and switches
8'h01: but_sw <= spi_byte_in;
8'h60: if (abyte_cnt < 5) joystick_0[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
8'h61: if (abyte_cnt < 5) joystick_1[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
8'h62: if (abyte_cnt < 5) joystick_2[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
8'h63: if (abyte_cnt < 5) joystick_3[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
8'h64: if (abyte_cnt < 5) joystick_4[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
8'h04: begin
// store incoming ps2 mouse bytes
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_byte_in;
ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
end
8'h05: begin
// store incoming ps2 keyboard bytes
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_byte_in;
ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
end
// joystick analog
8'h1a: begin
// first byte is joystick index
if(abyte_cnt == 1)
stick_idx <= spi_byte_in[2:0];
else if(abyte_cnt == 2) begin
// second byte is x axis
if(stick_idx == 0)
joystick_analog_0[15:8] <= spi_byte_in;
else if(stick_idx == 1)
joystick_analog_1[15:8] <= spi_byte_in;
end else if(abyte_cnt == 3) begin
// third byte is y axis
if(stick_idx == 0)
joystick_analog_0[7:0] <= spi_byte_in;
else if(stick_idx == 1)
joystick_analog_1[7:0] <= spi_byte_in;
end
end
8'h15: status <= spi_byte_in;
// status, 32bit version
8'h1e: if(abyte_cnt<5) status[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
endcase
end
end
end
// Process SD-card related bytes from SPI at the clk_sd domain
always @(posedge clk_sd) begin
reg spi_receiver_strobe;
reg spi_transfer_end;
reg spi_receiver_strobeD;
reg spi_transfer_endD;
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
if(sd_din_strobe) begin
sd_din_strobe<= 0;
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
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;
// fetch first byte when sectore FPGA->IO command has been seen
if(spi_byte_in == 8'h18)
sd_din_strobe <= 1'b1;
if((spi_byte_in == 8'h17) || (spi_byte_in == 8'h18))
sd_ack <= 1'b1;
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
// send sector FPGA -> IO
8'h18: sd_din_strobe <= 1'b1;
// 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 <= 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

1
mist-modules Submodule

Submodule mist-modules added at 232c10f768