mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 07:34:41 +00:00
BBC: use common MiST modules
This commit is contained in:
@@ -41,7 +41,7 @@ set_global_assignment -name DEVICE EP3C25E144C8
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY bbc_mist_top
|
||||
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:11:51 AUGUST 27, 2015"
|
||||
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 MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
@@ -55,10 +55,6 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
|
||||
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
|
||||
|
||||
set_location_assignment PIN_22 -to CLOCK_50[0]
|
||||
set_location_assignment PIN_23 -to CLOCK_50[1]
|
||||
set_location_assignment PIN_128 -to CLOCK_32[0]
|
||||
set_location_assignment PIN_129 -to CLOCK_32[1]
|
||||
set_location_assignment PIN_54 -to CLOCK_27[0]
|
||||
set_location_assignment PIN_55 -to CLOCK_27[1]
|
||||
set_location_assignment PIN_144 -to VGA_R[5]
|
||||
@@ -133,7 +129,7 @@ set_location_assignment PIN_65 -to AUDIO_L
|
||||
set_location_assignment PIN_80 -to AUDIO_R
|
||||
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp2.stp
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/dio.stp
|
||||
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
|
||||
set_global_assignment -name ENABLE_NCE_PIN OFF
|
||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
@@ -165,17 +161,9 @@ set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA ON
|
||||
set_global_assignment -name VERILOG_FILE bbc_mist_top.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rgb2ypbpr.sv
|
||||
set_global_assignment -name VERILOG_FILE sdram.v
|
||||
set_global_assignment -name VERILOG_FILE sd_card.v
|
||||
set_global_assignment -name VERILOG_FILE user_io.v
|
||||
set_global_assignment -name VERILOG_FILE osd.v
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
set_global_assignment -name VERILOG_FILE clockgen.v
|
||||
set_location_assignment PLL_1 -to CLOCKS|altpll_component|auto_generated|pll1
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/sigma_delta_dac.v
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/audio.v
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/scandoubler.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/adc.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/mc6845.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/ps2_intf.v
|
||||
@@ -206,4 +194,9 @@ set_global_assignment -name QIP_FILE os12.qip
|
||||
set_global_assignment -name QIP_FILE basic2.qip
|
||||
set_global_assignment -name QIP_FILE dfs09.qip
|
||||
set_global_assignment -name SDC_FILE bbc_mist.sdc
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE bbc_mist_top.sv
|
||||
set_global_assignment -name VERILOG_FILE sdram.v
|
||||
set_global_assignment -name VERILOG_FILE clockgen.v
|
||||
set_global_assignment -name QIP_FILE "../../../../mist-modules/mist.qip"
|
||||
set_global_assignment -name VERILOG_FILE "../../../../mist-modules/sd_card.v"
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
466
cores/bbc/fpga/mist/bbc_mist_top.sv
Normal file
466
cores/bbc/fpga/mist/bbc_mist_top.sv
Normal file
@@ -0,0 +1,466 @@
|
||||
`timescale 1ns / 1ps
|
||||
// bbc_mist_top.v
|
||||
module bbc_mist_top(
|
||||
|
||||
// clock inputs
|
||||
input wire [1:0] CLOCK_27, // 27 MHz
|
||||
|
||||
// LED outputs
|
||||
output wire LED, // LED Yellow
|
||||
|
||||
// VGA
|
||||
output wire VGA_HS, // VGA H_SYNC
|
||||
output wire VGA_VS, // VGA V_SYNC
|
||||
output wire [5:0] VGA_R, // VGA Red[5:0]
|
||||
output wire [5:0] VGA_G, // VGA Green[5:0]
|
||||
output wire [5:0] VGA_B, // VGA Blue[5:0];
|
||||
|
||||
// AUDIO
|
||||
output wire AUDIO_L, // sigma-delta DAC output left
|
||||
output wire AUDIO_R, // sigma-delta DAC output right
|
||||
|
||||
// SDRAM
|
||||
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
|
||||
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
|
||||
output SDRAM_DQML, // SDRAM Low-byte Data Mask
|
||||
output SDRAM_DQMH, // SDRAM High-byte Data Mask
|
||||
output SDRAM_nWE, // SDRAM Write Enable
|
||||
output SDRAM_nCAS, // SDRAM Column Address Strobe
|
||||
output SDRAM_nRAS, // SDRAM Row Address Strobe
|
||||
output SDRAM_nCS, // SDRAM Chip Select
|
||||
output [1:0] SDRAM_BA, // SDRAM Bank Address
|
||||
output SDRAM_CLK, // SDRAM Clock
|
||||
output SDRAM_CKE, // SDRAM Clock Enable
|
||||
|
||||
|
||||
// SPI
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SCK,
|
||||
input SPI_SS2, // data_io
|
||||
input SPI_SS3, // OSD
|
||||
input CONF_DATA0 // SPI_SS for user_io
|
||||
);
|
||||
|
||||
assign LED = 1'b0;
|
||||
|
||||
// the configuration string is returned to the io controller to allow
|
||||
// it to control the menu on the OSD
|
||||
parameter CONF_STR = {
|
||||
"BBC;ROM;",
|
||||
"O12,Scanlines,Off,25%,50%,75%;",
|
||||
"O3,Joystick Swap,Off,On;",
|
||||
"O4,ROM mapping,High,Low;",
|
||||
"O5,Auto boot,Off,On;",
|
||||
"T0,Reset;"
|
||||
};
|
||||
|
||||
wire [1:0] scanlines = status[2:1];
|
||||
wire joyswap = status[3];
|
||||
wire rommap = status[4];
|
||||
wire autoboot = status[5];
|
||||
|
||||
// generated clocks
|
||||
wire clk_32m /* synthesis keep */ ;
|
||||
wire clk_24m /* synthesis keep */ ;
|
||||
|
||||
wire pll_ready;
|
||||
|
||||
// core's raw video
|
||||
wire core_r, core_g, core_b, core_hs, core_vs;
|
||||
wire core_clken;
|
||||
|
||||
// memory bus signals.
|
||||
wire [14:0] vid_adr;
|
||||
wire [7:0] vid_data;
|
||||
|
||||
wire [15:0] mem_adr;
|
||||
wire [3:0] mem_romsel;
|
||||
|
||||
wire [7:0] mem_di;
|
||||
wire [7:0] rom_do;
|
||||
wire [7:0] ram_do;
|
||||
|
||||
wire [7:0] mem_do;
|
||||
wire mem_we;
|
||||
wire mem_sync;
|
||||
|
||||
// core's raw audio
|
||||
wire [15:0] coreaud_l, coreaud_r;
|
||||
|
||||
// user io
|
||||
wire [7:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
|
||||
wire ps2_clk;
|
||||
wire ps2_dat;
|
||||
|
||||
// the top file should generate the correct clocks for the machine
|
||||
|
||||
assign SDRAM_CLK = clk_32m;
|
||||
|
||||
clockgen CLOCKS(
|
||||
.inclk0 (CLOCK_27[0]),
|
||||
.c0 (clk_32m),
|
||||
.c1 (clk_24m),
|
||||
.locked (pll_ready) // pll locked output
|
||||
);
|
||||
|
||||
// conections between user_io (implementing the SPI communication
|
||||
// to the io controller) and the legacy
|
||||
wire [31:0] sd_lba;
|
||||
wire sd_rd;
|
||||
wire sd_wr;
|
||||
wire sd_ack;
|
||||
wire sd_conf;
|
||||
wire sd_sdhc;
|
||||
wire [7:0] sd_dout;
|
||||
wire sd_dout_strobe;
|
||||
wire [7:0] sd_din;
|
||||
wire sd_din_strobe;
|
||||
wire [8:0] sd_buff_addr;
|
||||
wire sd_ack_conf;
|
||||
wire img_mounted;
|
||||
wire [31:0] img_size;
|
||||
|
||||
wire [7:0] joystick_0;
|
||||
wire [7:0] joystick_1;
|
||||
wire [15:0] joystick_analog_0;
|
||||
wire [15:0] joystick_analog_1;
|
||||
|
||||
wire scandoubler_disable;
|
||||
wire ypbpr;
|
||||
wire no_csync;
|
||||
|
||||
user_io #(.STRLEN($size(CONF_STR)>>3)) user_io(
|
||||
.conf_str ( CONF_STR ),
|
||||
.clk_sys ( clk_32m ),
|
||||
.clk_sd ( clk_32m ),
|
||||
|
||||
// the spi interface
|
||||
.SPI_CLK ( SPI_SCK ),
|
||||
.SPI_SS_IO ( CONF_DATA0 ),
|
||||
.SPI_MISO ( SPI_DO ), // tristate handling inside user_io
|
||||
.SPI_MOSI ( SPI_DI ),
|
||||
|
||||
.joystick_0 ( joystick_0 ),
|
||||
.joystick_1 ( joystick_1 ),
|
||||
.joystick_analog_0 ( joystick_analog_0 ),
|
||||
.joystick_analog_1 ( joystick_analog_1 ),
|
||||
|
||||
.status ( status ),
|
||||
.switches ( switches ),
|
||||
.buttons ( buttons ),
|
||||
.scandoubler_disable ( scandoubler_disable ),
|
||||
.ypbpr ( ypbpr ),
|
||||
.no_csync ( no_csync ),
|
||||
|
||||
// interface to embedded legacy sd card wrapper
|
||||
.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_buff_addr ( sd_buff_addr ),
|
||||
.sd_ack_conf ( sd_ack_conf ),
|
||||
|
||||
.img_mounted ( img_mounted ),
|
||||
.img_size ( img_size ),
|
||||
|
||||
.ps2_kbd_clk ( ps2_clk ),
|
||||
.ps2_kbd_data ( ps2_dat )
|
||||
);
|
||||
|
||||
// wire the sd card to the user port
|
||||
wire sd_sck;
|
||||
wire sd_cs;
|
||||
wire sd_sdi;
|
||||
wire sd_sdo;
|
||||
|
||||
sd_card sd_card (
|
||||
// connection to io controller
|
||||
.clk_sys(clk_32m),
|
||||
.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_buff_dout (sd_dout),
|
||||
.sd_buff_wr (sd_dout_strobe),
|
||||
.sd_buff_din (sd_din),
|
||||
.sd_buff_addr (sd_buff_addr ),
|
||||
.img_mounted (img_mounted),
|
||||
.img_size (img_size),
|
||||
.allow_sdhc ( 1'b1),
|
||||
|
||||
// connection to local CPU
|
||||
.sd_cs ( sd_cs ),
|
||||
.sd_sck ( sd_sck ),
|
||||
.sd_sdi ( sd_sdi ),
|
||||
.sd_sdo ( sd_sdo )
|
||||
);
|
||||
|
||||
// data loading
|
||||
wire loader_active;
|
||||
wire loader_we, ioctl_we;
|
||||
wire [24:0] loader_addr, ioctl_addr;
|
||||
wire [7:0] loader_data, ioctl_data;
|
||||
|
||||
always @(posedge clk_32m) begin
|
||||
reg we_int = 0;
|
||||
|
||||
if (mem_sync) begin
|
||||
we_int <= 0;
|
||||
loader_we <= we_int;
|
||||
if (we_int) begin
|
||||
loader_addr <= ioctl_addr;
|
||||
loader_data <= ioctl_data;
|
||||
end
|
||||
end
|
||||
|
||||
if (ioctl_we) we_int <= 1;
|
||||
end
|
||||
|
||||
data_io #(.START_ADDR({ 7'b0000001, 4'ha, 14'h0 })) DATA_IO (
|
||||
.clk_sys ( clk_32m ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS2 ( SPI_SS2 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
|
||||
.ioctl_download ( loader_active ),
|
||||
|
||||
// ram interface
|
||||
.ioctl_wr ( ioctl_we ),
|
||||
.ioctl_addr ( ioctl_addr ),
|
||||
.ioctl_dout ( ioctl_data )
|
||||
);
|
||||
|
||||
wire [7:0] user_via_pb_out;
|
||||
wire user_via_cb1_in;
|
||||
wire user_via_cb2_in;
|
||||
|
||||
// reset core whenever the user changes the rom mapping
|
||||
reg last_rom_map;
|
||||
reg [11:0] rom_map_counter = 12'h0;
|
||||
always @(posedge clk_32m) begin
|
||||
last_rom_map <= rommap;
|
||||
|
||||
if(last_rom_map != rommap)
|
||||
rom_map_counter <= 12'hfff;
|
||||
else if(rom_map_counter != 0)
|
||||
rom_map_counter <= rom_map_counter - 12'd1;
|
||||
end
|
||||
|
||||
wire rom_remap_reset = (rom_map_counter != 0);
|
||||
|
||||
// the bbc is being reset of the pll isn't stable, if the ram isn't ready,
|
||||
// of the arm boots or if the user selects reset from the osd or of the user
|
||||
// presses the "core" button or the io controller uploads a rom
|
||||
wire reset_in = ~pll_ready || ~sdram_ready || status[0] ||
|
||||
buttons[1] || loader_active || rom_remap_reset;
|
||||
|
||||
// synchronize reset with memory state machine
|
||||
reg reset;
|
||||
always @(posedge mem_sync)
|
||||
reset <= reset_in;
|
||||
|
||||
// the autoboot feature simply works by pressing shift for 2 seconds after
|
||||
// the bbc has been reset
|
||||
wire autoboot_shift = autoboot && (autoboot_counter != 0 );
|
||||
reg [24:0] autoboot_counter;
|
||||
always @(posedge clk_32m) begin
|
||||
if(reset)
|
||||
autoboot_counter <= 25'd32000000;
|
||||
else if(autoboot_counter != 0)
|
||||
autoboot_counter <= autoboot_counter - 25'd1;
|
||||
end
|
||||
|
||||
bbc BBC(
|
||||
|
||||
.CLK32M_I ( clk_32m ),
|
||||
.CLK24M_I ( clk_24m ),
|
||||
.RESET_I ( reset ),
|
||||
|
||||
.HSYNC ( core_hs ),
|
||||
.VSYNC ( core_vs ),
|
||||
|
||||
.VIDEO_CLKEN( core_clken ),
|
||||
|
||||
.VIDEO_R ( core_r ),
|
||||
.VIDEO_G ( core_g ),
|
||||
.VIDEO_B ( core_b ),
|
||||
|
||||
.MEM_ADR ( mem_adr ),
|
||||
.MEM_WE ( mem_we ),
|
||||
.MEM_DO ( mem_do ),
|
||||
.MEM_DI ( mem_di ),
|
||||
.MEM_SYNC ( mem_sync ),
|
||||
.ROMSEL ( mem_romsel ),
|
||||
|
||||
.VID_ADR ( vid_adr ),
|
||||
.VID_DI ( vid_data ),
|
||||
|
||||
.SHIFT ( autoboot_shift ),
|
||||
|
||||
.SDCLK (sd_sck ),
|
||||
.SDSS (sd_cs ),
|
||||
.SDMISO (sd_sdo ),
|
||||
.SDMOSI (sd_sdi ),
|
||||
|
||||
.joy_but ( { joystick_1[4], joystick_0[4] } ),
|
||||
.joy0_axis0 ( joyswap ? joystick_analog_1[15:8] : joystick_analog_0[15:8] ),
|
||||
.joy0_axis1 ( joyswap ? joystick_analog_1[ 7:0] : joystick_analog_0[ 7:0] ),
|
||||
.joy1_axis0 ( joyswap ? joystick_analog_0[15:8] : joystick_analog_1[15:8] ),
|
||||
.joy1_axis1 ( joyswap ? joystick_analog_0[15:8] : joystick_analog_1[ 7:0] ),
|
||||
|
||||
.DIP_SWITCH ( 8'b00000000 ),
|
||||
|
||||
.PS2_CLK ( ps2_clk ),
|
||||
.PS2_DAT ( ps2_dat ),
|
||||
|
||||
.AUDIO_L ( coreaud_l ),
|
||||
.AUDIO_R ( coreaud_r )
|
||||
);
|
||||
|
||||
assign SDRAM_CKE = 1'b1;
|
||||
wire sdram_ready;
|
||||
|
||||
// cpu is accessing built-in core rom (mos or basic)
|
||||
wire cpu_ram = (mem_adr[15] == 1'b0);
|
||||
wire mos_rom = (mem_adr[15:14] == 2'b11);
|
||||
|
||||
wire [24:0] sdram_adr =
|
||||
loader_active?loader_addr:
|
||||
cpu_ram?{ 9'b000000000, mem_adr }: // ordinary ram access
|
||||
{ 7'b0000001, mem_romsel, mem_adr[13:0] }; // sideways ram/rom access
|
||||
|
||||
wire sdram_we = loader_active?loader_we:(mem_we && (cpu_ram || sideways_ram));
|
||||
|
||||
wire [7:0] sdram_di =
|
||||
loader_active?loader_data:mem_do;
|
||||
|
||||
sdram sdram (
|
||||
// interface to the MT48LC16M16 chip
|
||||
.sd_data ( SDRAM_DQ ),
|
||||
.sd_addr ( SDRAM_A ),
|
||||
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
|
||||
.sd_cs ( SDRAM_nCS ),
|
||||
.sd_ba ( SDRAM_BA ),
|
||||
.sd_we ( SDRAM_nWE ),
|
||||
.sd_ras ( SDRAM_nRAS ),
|
||||
.sd_cas ( SDRAM_nCAS ),
|
||||
|
||||
// system interface
|
||||
.clk ( clk_32m ),
|
||||
.sync ( mem_sync ),
|
||||
.init ( !pll_ready ),
|
||||
.ready ( sdram_ready ),
|
||||
|
||||
// cpu/video interface
|
||||
.cpu_di ( sdram_di ),
|
||||
.cpu_adr ( sdram_adr ),
|
||||
.cpu_we ( sdram_we ),
|
||||
.cpu_do ( ram_do ),
|
||||
|
||||
.vid_blnk ( loader_active ),
|
||||
.vid_adr ( { 9'd0, vid_adr } ),
|
||||
.vid_do ( vid_data )
|
||||
);
|
||||
|
||||
wire [7:0] os_do;
|
||||
os12 os12 (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( os_do )
|
||||
);
|
||||
|
||||
wire [7:0] basic_do;
|
||||
basic2 basic2 (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( basic_do )
|
||||
);
|
||||
|
||||
wire [7:0] mmfs_do;
|
||||
mmfs mmfs (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( mmfs_do )
|
||||
);
|
||||
|
||||
// map 64k sideways ram to bank 4,5,6 and 7
|
||||
wire sideways_ram =
|
||||
(mem_adr[15:14] == 2'b10) && (mem_romsel[3:2] == 2'b01);
|
||||
|
||||
// rommap is '1' of low mapping is selected in the menu
|
||||
wire basic_map = rommap?(mem_romsel == 4'h0):(mem_romsel == 4'he);
|
||||
wire mmfs_map = rommap?(mem_romsel == 4'h2):(mem_romsel == 4'hc);
|
||||
|
||||
assign mem_di =
|
||||
((mem_adr[15:14] == 2'b10) && basic_map) ? basic_do :
|
||||
((mem_adr[15:14] == 2'b10) && mmfs_map) ? mmfs_do :
|
||||
((mem_adr[15:14] == 2'b10) && (mem_romsel == 4'ha)) ? ram_do :
|
||||
mos_rom ? os_do :
|
||||
cpu_ram ? ram_do :
|
||||
sideways_ram ? ram_do :
|
||||
8'hff;
|
||||
|
||||
audio AUDIO (
|
||||
.clk ( clk_24m ),
|
||||
.rst ( ~pll_ready ),
|
||||
.audio_data_l( coreaud_l ),
|
||||
.audio_data_r( coreaud_r ),
|
||||
.audio_l ( AUDIO_L ),
|
||||
.audio_r ( AUDIO_R )
|
||||
);
|
||||
|
||||
mist_video #(.COLOR_DEPTH(1), .SD_HCNT_WIDTH(10)) mist_video (
|
||||
.clk_sys ( clk_32m ),
|
||||
|
||||
// OSD SPI interface
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS3 ( SPI_SS3 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
|
||||
// scanlines (00-none 01-25% 10-50% 11-75%)
|
||||
.scanlines ( scanlines ),
|
||||
|
||||
// non-scandoubled pixel clock divider 0 - clk_sys/4, 1 - clk_sys/2
|
||||
.ce_divider ( 1'b0 ),
|
||||
|
||||
// 0 = HVSync 31KHz, 1 = CSync 15KHz
|
||||
.scandoubler_disable ( scandoubler_disable ),
|
||||
// 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 ),
|
||||
|
||||
// video in
|
||||
.R ( core_r ),
|
||||
.G ( core_g ),
|
||||
.B ( core_b ),
|
||||
|
||||
.HSync ( core_hs ),
|
||||
.VSync ( core_vs ),
|
||||
|
||||
// MiST video output signals
|
||||
.VGA_R ( VGA_R ),
|
||||
.VGA_G ( VGA_G ),
|
||||
.VGA_B ( VGA_B ),
|
||||
.VGA_VS ( VGA_VS ),
|
||||
.VGA_HS ( VGA_HS )
|
||||
);
|
||||
|
||||
endmodule // bbc_mist_top
|
||||
@@ -1,496 +0,0 @@
|
||||
`timescale 1ns / 1ps
|
||||
// bbc_mist_top.v
|
||||
module bbc_mist_top(
|
||||
|
||||
// clock inputs
|
||||
input wire [1:0] CLOCK_27, // 27 MHz
|
||||
|
||||
// LED outputs
|
||||
output wire LED, // LED Yellow
|
||||
|
||||
// VGA
|
||||
output wire VGA_HS, // VGA H_SYNC
|
||||
output wire VGA_VS, // VGA V_SYNC
|
||||
output wire [5:0] VGA_R, // VGA Red[5:0]
|
||||
output wire [5:0] VGA_G, // VGA Green[5:0]
|
||||
output wire [5:0] VGA_B, // VGA Blue[5:0];
|
||||
|
||||
// AUDIO
|
||||
output wire AUDIO_L, // sigma-delta DAC output left
|
||||
output wire AUDIO_R, // sigma-delta DAC output right
|
||||
|
||||
// SDRAM
|
||||
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
|
||||
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
|
||||
output SDRAM_DQML, // SDRAM Low-byte Data Mask
|
||||
output SDRAM_DQMH, // SDRAM High-byte Data Mask
|
||||
output SDRAM_nWE, // SDRAM Write Enable
|
||||
output SDRAM_nCAS, // SDRAM Column Address Strobe
|
||||
output SDRAM_nRAS, // SDRAM Row Address Strobe
|
||||
output SDRAM_nCS, // SDRAM Chip Select
|
||||
output [1:0] SDRAM_BA, // SDRAM Bank Address
|
||||
output SDRAM_CLK, // SDRAM Clock
|
||||
output SDRAM_CKE, // SDRAM Clock Enable
|
||||
|
||||
|
||||
// SPI
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SCK,
|
||||
input SPI_SS2, // data_io
|
||||
input SPI_SS3, // OSD
|
||||
input CONF_DATA0 // SPI_SS for user_io
|
||||
);
|
||||
|
||||
assign LED = 1'b0;
|
||||
|
||||
// the configuration string is returned to the io controller to allow
|
||||
// it to control the menu on the OSD
|
||||
parameter CONF_STR = {
|
||||
"BBC;ROM;",
|
||||
"O1,Scanlines,Off,On;",
|
||||
"O2,ROM mapping,High,Low;",
|
||||
"O3,Auto boot,Off,On;",
|
||||
"T4,Reset;"
|
||||
};
|
||||
|
||||
parameter CONF_STR_LEN = 8+20+24+20+9;
|
||||
|
||||
// generated clocks
|
||||
wire clk_32m /* synthesis keep */ ;
|
||||
wire clk_24m /* synthesis keep */ ;
|
||||
|
||||
wire pll_ready;
|
||||
|
||||
// core's raw video
|
||||
wire core_r, core_g, core_b, core_hs, core_vs;
|
||||
wire core_clken;
|
||||
|
||||
// memory bus signals.
|
||||
wire [14:0] vid_adr;
|
||||
wire [7:0] vid_data;
|
||||
|
||||
wire [15:0] mem_adr;
|
||||
wire [3:0] mem_romsel;
|
||||
|
||||
wire [7:0] mem_di;
|
||||
wire [7:0] rom_do;
|
||||
wire [7:0] ram_do;
|
||||
|
||||
wire [7:0] mem_do;
|
||||
wire mem_we;
|
||||
wire mem_sync;
|
||||
|
||||
// core's raw audio
|
||||
wire [15:0] coreaud_l, coreaud_r;
|
||||
|
||||
// user io
|
||||
wire [7:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
|
||||
wire ps2_clk;
|
||||
wire ps2_dat;
|
||||
|
||||
// the top file should generate the correct clocks for the machine
|
||||
|
||||
assign SDRAM_CLK = !clk_32m;
|
||||
|
||||
clockgen CLOCKS(
|
||||
.inclk0 (CLOCK_27[0]),
|
||||
.c0 (clk_32m),
|
||||
.c1 (clk_24m),
|
||||
.locked (pll_ready) // pll locked output
|
||||
);
|
||||
|
||||
// without scan doubler only half the pixel clock is used
|
||||
reg clk_12m;
|
||||
always @(posedge clk_24m)
|
||||
clk_12m <= !clk_12m;
|
||||
|
||||
wire ce_pix = scandoubler_disable?clk_12m:1'd1;
|
||||
wire [5:0] osd_r_o, osd_g_o, osd_b_o;
|
||||
|
||||
osd #(0,0,4) OSD (
|
||||
.clk_sys ( clk_24m ),
|
||||
.ce_pix ( ce_pix ),
|
||||
|
||||
// spi for OSD
|
||||
.sdi ( SPI_DI ),
|
||||
.sck ( SPI_SCK ),
|
||||
.ss ( SPI_SS3 ),
|
||||
|
||||
.red_in ( scandoubler_disable? {5{video_r[0]}} : {3{video_r}} ),
|
||||
.green_in ( scandoubler_disable? {5{video_g[0]}} : {3{video_g}} ),
|
||||
.blue_in ( scandoubler_disable? {5{video_b[0]}} : {3{video_b}} ),
|
||||
|
||||
.hs_in ( video_hs ),
|
||||
.vs_in ( video_vs ),
|
||||
|
||||
.red_out ( osd_r_o ),
|
||||
.green_out ( osd_g_o ),
|
||||
.blue_out ( osd_b_o ),
|
||||
.hs_out ( v_hs ),
|
||||
.vs_out ( v_vs )
|
||||
);
|
||||
|
||||
wire [5:0] Y, Pb, Pr;
|
||||
|
||||
rgb2ypbpr rgb2ypbpr
|
||||
(
|
||||
.red ( osd_r_o ),
|
||||
.green ( osd_g_o ),
|
||||
.blue ( osd_b_o ),
|
||||
.y ( Y ),
|
||||
.pb ( Pb ),
|
||||
.pr ( Pr )
|
||||
);
|
||||
|
||||
wire v_hs, v_vs;
|
||||
|
||||
// create composite sync for 15khz
|
||||
wire csync = !(v_vs ^ v_hs);
|
||||
assign VGA_HS = (scandoubler_disable || ypbpr) ?csync:v_hs;
|
||||
assign VGA_VS = (scandoubler_disable || ypbpr) ?1'b1:v_vs;
|
||||
assign VGA_R = ypbpr?Pr:osd_r_o;
|
||||
assign VGA_G = ypbpr? Y:osd_g_o;
|
||||
assign VGA_B = ypbpr?Pb:osd_b_o;
|
||||
|
||||
// conections between user_io (implementing the SPIU communication
|
||||
// to the io controller) and the legacy
|
||||
wire [31:0] sd_lba;
|
||||
wire sd_rd;
|
||||
wire sd_wr;
|
||||
wire sd_ack;
|
||||
wire sd_conf;
|
||||
wire sd_sdhc;
|
||||
wire [7:0] sd_dout;
|
||||
wire sd_dout_strobe;
|
||||
wire [7:0] sd_din;
|
||||
wire sd_din_strobe;
|
||||
wire [8:0] sd_buff_addr;
|
||||
wire sd_ack_conf;
|
||||
wire img_mounted;
|
||||
wire [31:0] img_size;
|
||||
|
||||
wire [7:0] joystick_0;
|
||||
wire [7:0] joystick_1;
|
||||
wire [15:0] joystick_analog_0;
|
||||
wire [15:0] joystick_analog_1;
|
||||
|
||||
wire scandoubler_disable;
|
||||
wire ypbpr;
|
||||
|
||||
user_io #(.STRLEN(CONF_STR_LEN)) user_io(
|
||||
.conf_str ( CONF_STR ),
|
||||
.clk_sys(clk_32m),
|
||||
.clk_sd(clk_32m),
|
||||
|
||||
// the spi interface
|
||||
.SPI_CLK ( SPI_SCK ),
|
||||
.SPI_SS_IO ( CONF_DATA0 ),
|
||||
.SPI_MISO ( SPI_DO ), // tristate handling inside user_io
|
||||
.SPI_MOSI ( SPI_DI ),
|
||||
|
||||
// use mist joystick 1 as bbc primary joystick
|
||||
.joystick_0 ( joystick_1 ),
|
||||
.joystick_1 ( joystick_0 ),
|
||||
.joystick_analog_0 ( joystick_analog_1 ),
|
||||
.joystick_analog_1 ( joystick_analog_0 ),
|
||||
|
||||
.status ( status ),
|
||||
.switches ( switches ),
|
||||
.buttons ( buttons ),
|
||||
.scandoubler_disable ( scandoubler_disable ),
|
||||
.ypbpr ( ypbpr ),
|
||||
|
||||
// interface to embedded legacy sd card wrapper
|
||||
.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_buff_addr ( sd_buff_addr ),
|
||||
.sd_ack_conf ( sd_ack_conf ),
|
||||
|
||||
.img_mounted ( img_mounted ),
|
||||
.img_size ( img_size ),
|
||||
|
||||
.ps2_kbd_clk ( ps2_clk ),
|
||||
.ps2_kbd_data ( ps2_dat )
|
||||
);
|
||||
|
||||
// wire the sd card to the user port
|
||||
wire sd_sck;
|
||||
wire sd_cs;
|
||||
wire sd_sdi;
|
||||
wire sd_sdo;
|
||||
|
||||
sd_card sd_card (
|
||||
// connection to io controller
|
||||
.clk_sys(clk_32m),
|
||||
.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_buff_dout (sd_dout),
|
||||
.sd_buff_wr (sd_dout_strobe),
|
||||
.sd_buff_din (sd_din),
|
||||
.sd_buff_addr (sd_buff_addr ),
|
||||
.img_mounted (img_mounted),
|
||||
.img_size (img_size),
|
||||
.allow_sdhc ( 1'b1),
|
||||
|
||||
// connection to local CPU
|
||||
.sd_cs ( sd_cs ),
|
||||
.sd_sck ( sd_sck ),
|
||||
.sd_sdi ( sd_sdi ),
|
||||
.sd_sdo ( sd_sdo )
|
||||
);
|
||||
|
||||
// data loading
|
||||
wire loader_active;
|
||||
wire loader_we;
|
||||
wire [24:0] loader_addr;
|
||||
wire [7:0] loader_data;
|
||||
|
||||
data_io DATA_IO (
|
||||
.sck ( SPI_SCK ),
|
||||
.ss ( SPI_SS2 ),
|
||||
.sdi ( SPI_DI ),
|
||||
|
||||
.downloading ( loader_active ),
|
||||
.index ( ),
|
||||
|
||||
// ram interface
|
||||
.clk ( mem_sync ),
|
||||
.wr ( loader_we ),
|
||||
.addr ( loader_addr ),
|
||||
.data ( loader_data )
|
||||
);
|
||||
|
||||
wire [7:0] user_via_pb_out;
|
||||
wire user_via_cb1_in;
|
||||
wire user_via_cb2_in;
|
||||
|
||||
// reset core whenever the user changes the rom mapping
|
||||
reg last_rom_map;
|
||||
reg [11:0] rom_map_counter = 12'h0;
|
||||
always @(posedge clk_32m) begin
|
||||
last_rom_map <= status[2];
|
||||
|
||||
if(last_rom_map != status[2])
|
||||
rom_map_counter <= 12'hfff;
|
||||
else if(rom_map_counter != 0)
|
||||
rom_map_counter <= rom_map_counter - 12'd1;
|
||||
end
|
||||
|
||||
wire rom_remap_reset = (rom_map_counter != 0);
|
||||
|
||||
// the bbc is being reset of the pll isn't stable, if the ram isn't ready,
|
||||
// of the arm boots or if the user selects reset from the osd or of the user
|
||||
// presses the "core" button or the io controller uploads a rom
|
||||
wire reset_in = ~pll_ready || ~sdram_ready || status[0] || status[4] ||
|
||||
buttons[1] || loader_active || rom_remap_reset;
|
||||
|
||||
// synchronize reset with memory state machine
|
||||
reg reset;
|
||||
always @(posedge mem_sync)
|
||||
reset <= reset_in;
|
||||
|
||||
// the autoboot feature simply works by pressing shift for 2 seconds after
|
||||
// the bbc has been reset
|
||||
wire autoboot_shift = status[3] && (autoboot_counter != 0 );
|
||||
reg [24:0] autoboot_counter;
|
||||
always @(posedge clk_32m) begin
|
||||
if(reset)
|
||||
autoboot_counter <= 25'd32000000;
|
||||
else if(autoboot_counter != 0)
|
||||
autoboot_counter <= autoboot_counter - 25'd1;
|
||||
end
|
||||
|
||||
bbc BBC(
|
||||
|
||||
.CLK32M_I ( clk_32m ),
|
||||
.CLK24M_I ( clk_24m ),
|
||||
.RESET_I ( reset ),
|
||||
|
||||
.HSYNC ( core_hs ),
|
||||
.VSYNC ( core_vs ),
|
||||
|
||||
.VIDEO_CLKEN ( core_clken ),
|
||||
|
||||
.VIDEO_R ( core_r ),
|
||||
.VIDEO_G ( core_g ),
|
||||
.VIDEO_B ( core_b ),
|
||||
|
||||
.MEM_ADR ( mem_adr ),
|
||||
.MEM_WE ( mem_we ),
|
||||
.MEM_DO ( mem_do ),
|
||||
.MEM_DI ( mem_di ),
|
||||
.MEM_SYNC ( mem_sync ),
|
||||
.ROMSEL ( mem_romsel ),
|
||||
|
||||
.VID_ADR ( vid_adr ),
|
||||
.VID_DI ( vid_data ),
|
||||
|
||||
.SHIFT ( autoboot_shift ),
|
||||
|
||||
.SDCLK (sd_sck ),
|
||||
.SDSS (sd_cs ),
|
||||
.SDMISO (sd_sdo ),
|
||||
.SDMOSI (sd_sdi ),
|
||||
|
||||
.joy_but ( { joystick_1[4], joystick_0[4] } ),
|
||||
.joy0_axis0 ( joystick_analog_0[15:8] ),
|
||||
.joy0_axis1 ( joystick_analog_0[7:0] ),
|
||||
.joy1_axis0 ( joystick_analog_1[15:8] ),
|
||||
.joy1_axis1 ( joystick_analog_1[7:0] ),
|
||||
|
||||
.DIP_SWITCH ( 8'b00000000 ),
|
||||
|
||||
.PS2_CLK ( ps2_clk ),
|
||||
.PS2_DAT ( ps2_dat ),
|
||||
|
||||
.AUDIO_L ( coreaud_l ),
|
||||
.AUDIO_R ( coreaud_r )
|
||||
|
||||
);
|
||||
|
||||
assign SDRAM_CKE = 1'b1;
|
||||
wire sdram_ready;
|
||||
|
||||
// cpu is accessing built-in core rom (mos or basic)
|
||||
wire cpu_ram = (mem_adr[15] == 1'b0);
|
||||
wire mos_rom = (mem_adr[15:14] == 2'b11);
|
||||
|
||||
wire [24:0] sdram_adr =
|
||||
loader_active?loader_addr:
|
||||
cpu_ram?{ 9'b000000000, mem_adr }: // ordinary ram access
|
||||
{ 7'b0000001, mem_romsel, mem_adr[13:0] }; // sideways ram/rom access
|
||||
|
||||
wire sdram_we = loader_active?loader_we:(mem_we && (cpu_ram || sideways_ram));
|
||||
|
||||
wire [7:0] sdram_di =
|
||||
loader_active?loader_data:mem_do;
|
||||
|
||||
sdram sdram (
|
||||
// interface to the MT48LC16M16 chip
|
||||
.sd_data ( SDRAM_DQ ),
|
||||
.sd_addr ( SDRAM_A ),
|
||||
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
|
||||
.sd_cs ( SDRAM_nCS ),
|
||||
.sd_ba ( SDRAM_BA ),
|
||||
.sd_we ( SDRAM_nWE ),
|
||||
.sd_ras ( SDRAM_nRAS ),
|
||||
.sd_cas ( SDRAM_nCAS ),
|
||||
|
||||
// system interface
|
||||
.clk ( clk_32m ),
|
||||
.sync ( mem_sync ),
|
||||
.init ( !pll_ready ),
|
||||
.ready ( sdram_ready ),
|
||||
|
||||
// cpu/video interface
|
||||
.cpu_di ( sdram_di ),
|
||||
.cpu_adr ( sdram_adr ),
|
||||
.cpu_we ( sdram_we ),
|
||||
.cpu_do ( ram_do ),
|
||||
|
||||
.vid_blnk ( loader_active ),
|
||||
.vid_adr ( { 9'd0, vid_adr } ),
|
||||
.vid_do ( vid_data )
|
||||
);
|
||||
|
||||
wire [7:0] os_do;
|
||||
os12 os12 (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( os_do )
|
||||
);
|
||||
|
||||
wire [7:0] basic_do;
|
||||
basic2 basic2 (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( basic_do )
|
||||
);
|
||||
|
||||
wire [7:0] mmfs_do;
|
||||
mmfs mmfs (
|
||||
.clock ( clk_32m ),
|
||||
.address ( mem_adr[13:0] ),
|
||||
.q ( mmfs_do )
|
||||
);
|
||||
|
||||
audio AUDIO (
|
||||
.clk ( clk_24m ),
|
||||
.rst ( ~pll_ready ),
|
||||
.audio_data_l ( coreaud_l ),
|
||||
.audio_data_r ( coreaud_r ),
|
||||
.audio_l ( AUDIO_L ),
|
||||
.audio_r ( AUDIO_R )
|
||||
);
|
||||
|
||||
wire sd_hs, sd_vs;
|
||||
wire [1:0] sd_r;
|
||||
wire [1:0] sd_g;
|
||||
wire [1:0] sd_b;
|
||||
|
||||
scandoubler SCANDOUBLE(
|
||||
|
||||
.clk_16 ( clk_32m ),
|
||||
.clk_16_en ( core_clken ),
|
||||
|
||||
.scanlines ( status[1] ),
|
||||
|
||||
.vs_in ( core_vs ),
|
||||
.hs_in ( core_hs ),
|
||||
|
||||
.r_in ( core_r ),
|
||||
.g_in ( core_g ),
|
||||
.b_in ( core_b ),
|
||||
|
||||
.clk ( clk_32m ),
|
||||
|
||||
.vs_out ( sd_vs ),
|
||||
.hs_out ( sd_hs ),
|
||||
|
||||
.r_out ( sd_r ),
|
||||
.g_out ( sd_g ),
|
||||
.b_out ( sd_b )
|
||||
);
|
||||
|
||||
// switch between doubled and non-doubled video
|
||||
wire [1:0] video_r = scandoubler_disable?core_r:sd_r;
|
||||
wire [1:0] video_g = scandoubler_disable?core_g:sd_g;
|
||||
wire [1:0] video_b = scandoubler_disable?core_b:sd_b;
|
||||
wire video_hs = scandoubler_disable?core_hs:sd_hs;
|
||||
wire video_vs = scandoubler_disable?core_vs:sd_vs;
|
||||
|
||||
// map 64k sideways ram to bank 4,5,6 and 7
|
||||
wire sideways_ram =
|
||||
(mem_adr[15:14] == 2'b10) && (mem_romsel[3:2] == 2'b01);
|
||||
|
||||
// status[2] is '1' of low mapping is selected in the menu
|
||||
wire basic_map = status[2]?(mem_romsel == 4'h0):(mem_romsel == 4'he);
|
||||
wire mmfs_map = status[2]?(mem_romsel == 4'h2):(mem_romsel == 4'hc);
|
||||
|
||||
assign mem_di =
|
||||
((mem_adr[15:14] == 2'b10) && basic_map) ? basic_do :
|
||||
((mem_adr[15:14] == 2'b10) && mmfs_map) ? mmfs_do :
|
||||
((mem_adr[15:14] == 2'b10) && (mem_romsel == 4'ha)) ? ram_do :
|
||||
mos_rom ? os_do :
|
||||
cpu_ram ? ram_do :
|
||||
sideways_ram ? ram_do :
|
||||
8'hff;
|
||||
|
||||
endmodule // bbc_mist_top
|
||||
@@ -1,134 +0,0 @@
|
||||
//
|
||||
// data_io.v
|
||||
//
|
||||
// io controller writable ram for the MiST board
|
||||
// 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 data_io (
|
||||
// io controller spi interface
|
||||
input sck,
|
||||
input ss,
|
||||
input sdi,
|
||||
|
||||
output downloading, // signal indicating an active download
|
||||
output reg [4:0] index, // menu index used to upload the file
|
||||
|
||||
// external ram interface
|
||||
input clk,
|
||||
output reg wr,
|
||||
output reg [24:0] addr,
|
||||
output reg [7:0] data
|
||||
);
|
||||
|
||||
// *********************************************************************************
|
||||
// spi client
|
||||
// *********************************************************************************
|
||||
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [3:0] cnt;
|
||||
reg rclk;
|
||||
|
||||
reg [24:0] laddr;
|
||||
reg [7:0] ldata;
|
||||
|
||||
localparam UIO_FILE_TX = 8'h53;
|
||||
localparam UIO_FILE_TX_DAT = 8'h54;
|
||||
localparam UIO_FILE_INDEX = 8'h55;
|
||||
|
||||
assign downloading = downloading_reg;
|
||||
reg downloading_reg = 1'b0;
|
||||
|
||||
// filter spi clock. the 8 bit gate delay is ~2.5ns in total
|
||||
wire [7:0] spi_sck_D = { spi_sck_D[6:0], sck } /* synthesis keep */;
|
||||
wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
|
||||
|
||||
// data_io has its own SPI interface to the io controller
|
||||
always@(posedge spi_sck, posedge ss) begin
|
||||
if(ss == 1'b1)
|
||||
cnt <= 4'd0;
|
||||
else begin
|
||||
rclk <= 1'b0;
|
||||
|
||||
// don't shift in last bit. It is evaluated directly
|
||||
// when writing to ram
|
||||
if(cnt[2:0] != 3'd7)
|
||||
sbuf <= { sbuf[5:0], sdi};
|
||||
|
||||
// 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};
|
||||
|
||||
if(cnt == 15) begin
|
||||
|
||||
// prepare/end transmission
|
||||
if(cmd == UIO_FILE_TX) begin
|
||||
// prepare
|
||||
if(sdi) begin
|
||||
// download rom into sideways rom slot e
|
||||
laddr <= { 7'b0000001, 4'ha, 14'h0 } - 25'd1;
|
||||
downloading_reg <= 1'b1;
|
||||
end else
|
||||
downloading_reg <= 1'b0;
|
||||
end
|
||||
|
||||
// command 0x54: UIO_FILE_TX
|
||||
if(cmd == UIO_FILE_TX_DAT) begin
|
||||
ldata <= {sbuf, sdi};
|
||||
laddr <= laddr + 25'd1;
|
||||
rclk <= 1'b1;
|
||||
end
|
||||
|
||||
// expose file (menu) index
|
||||
if(cmd == UIO_FILE_INDEX)
|
||||
index <= {sbuf[3:0], sdi};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg mem_req;
|
||||
always @(posedge rclk or posedge wr) begin
|
||||
if(wr) mem_req <= 1'b0;
|
||||
else mem_req <= 1'b1;
|
||||
end
|
||||
|
||||
// memory request needs to be valid on the rising
|
||||
// edge so data and address are sure stable in it's
|
||||
// falling edge
|
||||
reg mem_reqD;
|
||||
always@(posedge clk)
|
||||
mem_reqD <= mem_req;
|
||||
|
||||
always@(negedge clk) begin
|
||||
wr <= 1'b0;
|
||||
|
||||
if(mem_reqD) begin
|
||||
addr <= laddr;
|
||||
data <= ldata;
|
||||
wr <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,209 +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_width = vs_pol?vs_low:vs_high;
|
||||
wire [9:0] v_dsp_ctr = { 1'b0, v_dsp_width[9:1] };
|
||||
|
||||
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;
|
||||
wire [9:0] v_osd_start = v_dsp_ctr + OSD_Y_OFFSET - (OSD_HEIGHT >> 1);
|
||||
wire [9:0] v_osd_end = v_dsp_ctr + OSD_Y_OFFSET + (OSD_HEIGHT >> 1) - 1;
|
||||
|
||||
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 [7:0] osd_hcnt = h_cnt - h_osd_start + 7'd1; // one pixel offset for osd_byte register
|
||||
wire [6:0] osd_vcnt = v_cnt - v_osd_start;
|
||||
|
||||
wire osd_pixel = osd_byte[osd_vcnt[3:1]];
|
||||
|
||||
reg [7:0] osd_byte;
|
||||
always @(posedge clk_sys)
|
||||
if (ce_pix) osd_byte <= osd_buffer[{osd_vcnt[6:4], osd_hcnt}];
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -1,467 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
module sd_card (
|
||||
input clk_sys,
|
||||
// link to user_io for io controller
|
||||
output [31:0] sd_lba,
|
||||
output reg sd_rd,
|
||||
output reg sd_wr,
|
||||
input sd_ack,
|
||||
input sd_ack_conf,
|
||||
output sd_conf,
|
||||
output sd_sdhc,
|
||||
|
||||
input img_mounted,
|
||||
input [31:0] img_size,
|
||||
|
||||
output reg sd_busy = 0,
|
||||
// data coming in from io controller
|
||||
input [7:0] sd_buff_dout,
|
||||
input sd_buff_wr,
|
||||
|
||||
// data going out to io controller
|
||||
output [7:0] sd_buff_din,
|
||||
|
||||
input [8:0] sd_buff_addr,
|
||||
|
||||
// configuration input
|
||||
input allow_sdhc,
|
||||
|
||||
input sd_cs,
|
||||
input sd_sck,
|
||||
input sd_sdi,
|
||||
output reg sd_sdo
|
||||
);
|
||||
|
||||
wire [31:0] OCR = { 1'b1, sd_sdhc, 6'h0, 9'h1f, 15'h0 }; // bit31 = finished powerup
|
||||
// bit30 = 1 -> high capaciry card (sdhc)
|
||||
// 15-23 supported voltage range
|
||||
wire [7:0] READ_DATA_TOKEN = 8'hfe;
|
||||
|
||||
// number of bytes to wait after a command before sending the reply
|
||||
localparam NCR=4;
|
||||
|
||||
localparam RD_STATE_IDLE = 2'd0;
|
||||
localparam RD_STATE_WAIT_IO = 2'd1;
|
||||
localparam RD_STATE_SEND_TOKEN = 2'd2;
|
||||
localparam RD_STATE_SEND_DATA = 2'd3;
|
||||
reg [1:0] read_state = RD_STATE_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 card_is_reset = 1'b0; // flag that card has received a reset command
|
||||
reg [6:0] sbuf;
|
||||
reg cmd55;
|
||||
reg [7:0] cmd = 8'h00;
|
||||
reg [2:0] bit_cnt = 3'd0; // counts bits 0-7 0-7 ...
|
||||
reg [3:0] byte_cnt= 4'd15; // counts bytes
|
||||
|
||||
reg [39:0] args;
|
||||
assign sd_lba = sd_sdhc?args[39:8]:{9'd0, args[39:17]};
|
||||
|
||||
reg [7:0] reply;
|
||||
reg [7:0] reply0, reply1, reply2, reply3;
|
||||
reg [3:0] reply_len;
|
||||
|
||||
// ------------------------- SECTOR BUFFER -----------------------
|
||||
|
||||
// the buffer itself. Can hold one sector
|
||||
reg [8:0] buffer_ptr;
|
||||
wire [7:0] buffer_dout;
|
||||
reg [7:0] buffer_din;
|
||||
reg buffer_write_strobe;
|
||||
|
||||
sd_card_dpram #(8, 9) buffer_dpram
|
||||
(
|
||||
.clock_a (clk_sys),
|
||||
.address_a (sd_buff_addr),
|
||||
.data_a (sd_buff_dout),
|
||||
.wren_a (sd_buff_wr & sd_ack),
|
||||
.q_a (sd_buff_din),
|
||||
|
||||
.clock_b (clk_sys),
|
||||
.address_b (buffer_ptr),
|
||||
.data_b (buffer_din),
|
||||
.wren_b (buffer_write_strobe),
|
||||
.q_b (buffer_dout)
|
||||
);
|
||||
|
||||
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;
|
||||
|
||||
// ------------------------- CSD/CID BUFFER ----------------------
|
||||
reg [7:0] conf;
|
||||
assign sd_conf = sd_configuring;
|
||||
|
||||
reg sd_configuring = 1;
|
||||
reg [4:0] conf_buff_ptr;
|
||||
reg [7:0] conf_byte;
|
||||
reg[255:0] csdcid;
|
||||
|
||||
// conf[0]==1 -> io controller is using an sdhc card
|
||||
wire sd_has_sdhc = conf[0];
|
||||
assign sd_sdhc = allow_sdhc && sd_has_sdhc;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg old_mounted;
|
||||
|
||||
if (sd_buff_wr & sd_ack_conf) begin
|
||||
if (sd_buff_addr == 32) begin
|
||||
conf <= sd_buff_dout;
|
||||
sd_configuring <= 0;
|
||||
end
|
||||
else csdcid[(31-sd_buff_addr) << 3 +:8] <= sd_buff_dout;
|
||||
end
|
||||
conf_byte <= csdcid[(31-conf_buff_ptr) << 3 +:8];
|
||||
|
||||
old_mounted <= img_mounted;
|
||||
if (~old_mounted & img_mounted) begin
|
||||
// update card size in case of a virtual SD image
|
||||
if (sd_sdhc)
|
||||
// CSD V1.0 size = (c_size + 1) * 512K
|
||||
csdcid[69:48] <= {9'd0, img_size[31:19] };
|
||||
else begin
|
||||
// CSD V2.0 no. of blocks = c_size ** (c_size_mult + 2)
|
||||
csdcid[49:47] <= 3'd7; //c_size_mult
|
||||
csdcid[73:62] <= img_size[29:18]; //c_size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always@(posedge clk_sys) begin
|
||||
|
||||
reg old_sd_sck;
|
||||
reg [5:0] ack;
|
||||
|
||||
ack <= {ack[4:0], sd_ack};
|
||||
if(ack[5:4] == 'b01) { sd_rd, sd_wr } <= 2'b00;
|
||||
if(ack[5:4] == 'b10) sd_busy <= 0;
|
||||
|
||||
buffer_write_strobe <= 0;
|
||||
if (buffer_write_strobe) buffer_ptr <= buffer_ptr + 1'd1;
|
||||
|
||||
old_sd_sck <= sd_sck;
|
||||
// advance transmitter state machine on falling sck edge, so data is valid on the
|
||||
// rising edge
|
||||
// ----------------- spi transmitter --------------------
|
||||
if(sd_cs == 0 && old_sd_sck && ~sd_sck) begin
|
||||
|
||||
sd_sdo <= 1'b1; // default: send 1's (busy/wait)
|
||||
|
||||
if(byte_cnt == 5+NCR) begin
|
||||
sd_sdo <= reply[~bit_cnt];
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
// these three commands all have a reply_len of 0 and will thus
|
||||
// not send more than a single reply byte
|
||||
|
||||
// CMD9: SEND_CSD
|
||||
// CMD10: SEND_CID
|
||||
if((cmd == 8'h49)||(cmd == 8'h4a))
|
||||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||||
|
||||
// CMD17: READ_SINGLE_BLOCK
|
||||
if(cmd == 8'h51) begin
|
||||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||||
sd_rd <= 1; // trigger request to io controller
|
||||
sd_busy <= 1;
|
||||
end
|
||||
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;
|
||||
|
||||
// ---------- read state machine processing -------------
|
||||
|
||||
case(read_state)
|
||||
RD_STATE_IDLE: ;
|
||||
// don't do anything
|
||||
|
||||
// waiting for io controller to return data
|
||||
RD_STATE_WAIT_IO: begin
|
||||
buffer_ptr <= 0;
|
||||
if(~sd_busy && (bit_cnt == 7))
|
||||
read_state <= RD_STATE_SEND_TOKEN;
|
||||
end
|
||||
|
||||
// send data token
|
||||
RD_STATE_SEND_TOKEN: begin
|
||||
sd_sdo <= READ_DATA_TOKEN[~bit_cnt];
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||||
conf_buff_ptr <= (cmd == 8'h4a) ? 5'h0 : 5'h10;
|
||||
end
|
||||
end
|
||||
|
||||
// send data
|
||||
RD_STATE_SEND_DATA: begin
|
||||
if(cmd == 8'h51) // CMD17: READ_SINGLE_BLOCK
|
||||
sd_sdo <= buffer_dout[~bit_cnt];
|
||||
else if(cmd == 8'h49) begin // CMD9: SEND_CSD
|
||||
sd_sdo <= conf_byte[~bit_cnt];
|
||||
end
|
||||
else if(cmd == 8'h4a) // CMD10: SEND_CID
|
||||
sd_sdo <= conf_byte[~bit_cnt];
|
||||
else
|
||||
sd_sdo <= 1'b1;
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
// sent 512 sector data bytes?
|
||||
if((cmd == 8'h51) && &buffer_ptr) // (buffer_ptr ==511))
|
||||
read_state <= RD_STATE_IDLE; // next: send crc. It's ignored so return to idle state
|
||||
|
||||
// sent 16 cid/csd data bytes?
|
||||
else if(((cmd == 8'h49)||(cmd == 8'h4a)) && conf_buff_ptr[3:0] == 4'h0f) // && (buffer_rptr == 16))
|
||||
read_state <= RD_STATE_IDLE; // return to idle state
|
||||
|
||||
else begin
|
||||
buffer_ptr <= buffer_ptr + 1'd1;
|
||||
conf_buff_ptr<= conf_buff_ptr+ 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// ------------------ 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
|
||||
|
||||
// spi receiver
|
||||
// cs is active low
|
||||
if(sd_cs == 1) begin
|
||||
bit_cnt <= 3'd0;
|
||||
end else if (~old_sd_sck & sd_sck) begin
|
||||
bit_cnt <= bit_cnt + 3'd1;
|
||||
|
||||
// assemble byte
|
||||
if(bit_cnt != 7)
|
||||
sbuf[6:0] <= { sbuf[5:0], sd_sdi };
|
||||
else begin
|
||||
// finished reading one byte
|
||||
// byte counter runs against 15 byte boundary
|
||||
if(byte_cnt != 15)
|
||||
byte_cnt <= byte_cnt + 4'd1;
|
||||
|
||||
// byte_cnt > 6 -> complete command received
|
||||
// first byte of valid command is 01xxxxxx
|
||||
// don't accept new commands once a write or read command has been accepted
|
||||
if((byte_cnt > 5) && (write_state == WR_STATE_IDLE) &&
|
||||
(read_state == RD_STATE_IDLE) && sbuf[6:5] == 2'b01) begin
|
||||
byte_cnt <= 4'd0;
|
||||
cmd <= { sbuf, sd_sdi};
|
||||
|
||||
// set cmd55 flag if previous command was 55
|
||||
cmd55 <= (cmd == 8'h77);
|
||||
end
|
||||
|
||||
// parse additional command bytes
|
||||
if(byte_cnt == 0) args[39:32] <= { sbuf, sd_sdi};
|
||||
if(byte_cnt == 1) args[31:24] <= { sbuf, sd_sdi};
|
||||
if(byte_cnt == 2) args[23:16] <= { sbuf, sd_sdi};
|
||||
if(byte_cnt == 3) args[15:8] <= { sbuf, sd_sdi};
|
||||
if(byte_cnt == 4) args[7:0] <= { sbuf, sd_sdi};
|
||||
|
||||
// last byte received, evaluate
|
||||
if(byte_cnt == 5) begin
|
||||
|
||||
// default:
|
||||
reply <= 8'h04; // illegal command
|
||||
reply_len <= 4'd0; // no extra reply bytes
|
||||
|
||||
// CMD0: GO_IDLE_STATE
|
||||
if(cmd == 8'h40) begin
|
||||
card_is_reset <= 1'b1;
|
||||
reply <= 8'h01; // ok, busy
|
||||
end
|
||||
|
||||
// every other command is only accepted after a reset
|
||||
else if(card_is_reset) begin
|
||||
case(cmd)
|
||||
// CMD1: SEND_OP_COND
|
||||
8'h41: reply <= 8'h00; // ok, not busy
|
||||
|
||||
// CMD8: SEND_IF_COND (V2 only)
|
||||
8'h48: begin
|
||||
reply <= 8'h01; // ok, busy
|
||||
reply0 <= 8'h00;
|
||||
reply1 <= 8'h00;
|
||||
reply2 <= { 4'b0, args[19:16] };
|
||||
reply3 <= args[15:8];
|
||||
reply_len <= 4'd4;
|
||||
end
|
||||
|
||||
// CMD9: SEND_CSD
|
||||
8'h49: reply <= 8'h00; // ok
|
||||
|
||||
// CMD10: SEND_CID
|
||||
8'h4a: reply <= 8'h00; // ok
|
||||
|
||||
// CMD16: SET_BLOCKLEN
|
||||
8'h50:
|
||||
// we only support a block size of 512
|
||||
if(args[39:8] == 32'd512)
|
||||
reply <= 8'h00; // ok
|
||||
else
|
||||
reply <= 8'h40; // parmeter error
|
||||
|
||||
// CMD17: READ_SINGLE_BLOCK
|
||||
8'h51: reply <= 8'h00; // ok
|
||||
|
||||
// CMD24: WRITE_BLOCK
|
||||
8'h58: begin
|
||||
reply <= 8'h00; // ok
|
||||
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
|
||||
end
|
||||
|
||||
// ACMD41: APP_SEND_OP_COND
|
||||
8'h69: if(cmd55) begin
|
||||
reply <= 8'h00; // ok, not busy
|
||||
end
|
||||
|
||||
// CMD55: APP_COND
|
||||
8'h77: reply <= 8'h01; // ok, busy
|
||||
|
||||
// CMD58: READ_OCR
|
||||
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
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ---------- handle write -----------
|
||||
case(write_state)
|
||||
// don't do anything in idle state
|
||||
WR_STATE_IDLE: ;
|
||||
|
||||
// waiting for data token
|
||||
WR_STATE_EXP_DTOKEN:
|
||||
if({ sbuf, sd_sdi} == 8'hfe ) begin
|
||||
write_state <= WR_STATE_RECV_DATA;
|
||||
buffer_ptr <= 9'd0;
|
||||
end
|
||||
|
||||
// transfer 512 bytes
|
||||
WR_STATE_RECV_DATA: begin
|
||||
// push one byte into local buffer
|
||||
buffer_write_strobe <= 1'b1;
|
||||
buffer_din <= { sbuf, sd_sdi };
|
||||
|
||||
// all bytes written?
|
||||
if(&buffer_ptr)
|
||||
write_state <= WR_STATE_RECV_CRC0;
|
||||
end
|
||||
|
||||
// transfer 1st crc byte
|
||||
WR_STATE_RECV_CRC0:
|
||||
write_state <= WR_STATE_RECV_CRC1;
|
||||
|
||||
// transfer 2nd crc byte
|
||||
WR_STATE_RECV_CRC1:
|
||||
write_state <= WR_STATE_SEND_DRESP;
|
||||
|
||||
// send data response
|
||||
WR_STATE_SEND_DRESP: begin
|
||||
write_state <= WR_STATE_BUSY;
|
||||
sd_wr <= 1; // trigger write request to io ontroller
|
||||
sd_busy <= 1;
|
||||
end
|
||||
|
||||
// wait for io controller to accept data
|
||||
WR_STATE_BUSY:
|
||||
if(~sd_busy)
|
||||
write_state <= WR_STATE_IDLE;
|
||||
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module sd_card_dpram #(parameter DATAWIDTH=8, ADDRWIDTH=9)
|
||||
(
|
||||
input clock_a,
|
||||
input [ADDRWIDTH-1:0] address_a,
|
||||
input [DATAWIDTH-1:0] data_a,
|
||||
input wren_a,
|
||||
output reg [DATAWIDTH-1:0] q_a,
|
||||
|
||||
input clock_b,
|
||||
input [ADDRWIDTH-1:0] address_b,
|
||||
input [DATAWIDTH-1:0] data_b,
|
||||
input wren_b,
|
||||
output reg [DATAWIDTH-1:0] q_b
|
||||
);
|
||||
|
||||
reg [DATAWIDTH-1:0] ram[0:(1<<ADDRWIDTH)-1];
|
||||
|
||||
always @(posedge clock_a) begin
|
||||
q_a <= ram[address_a];
|
||||
if(wren_a) begin
|
||||
q_a <= data_a;
|
||||
ram[address_a] <= data_a;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clock_b) begin
|
||||
q_b <= ram[address_b];
|
||||
if(wren_b) begin
|
||||
q_b <= data_b;
|
||||
ram[address_b] <= data_b;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -1,530 +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 sd_wrD;
|
||||
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
|
||||
|
||||
sd_din_strobe<= 0;
|
||||
sd_wrD <= sd_wr;
|
||||
// fetch the first byte immediately after the write command seen
|
||||
if (~sd_wrD & sd_wr) begin
|
||||
sd_buff_addr <= 0;
|
||||
sd_din_strobe <= 1;
|
||||
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;
|
||||
|
||||
if(spi_byte_in == 8'h18) begin
|
||||
sd_din_strobe <= 1'b1;
|
||||
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
end
|
||||
|
||||
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: begin
|
||||
sd_din_strobe <= 1'b1;
|
||||
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
end
|
||||
|
||||
// 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
|
||||
Reference in New Issue
Block a user