From 8d1826bd5f3e12babb54b882435982bbde6ba578 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Tue, 18 Feb 2020 16:00:35 +0100 Subject: [PATCH] BBC: use common MiST modules --- cores/bbc/fpga/mist/bbc_mist_top.qsf | 23 +- cores/bbc/fpga/mist/bbc_mist_top.sv | 466 +++++++++++++++++++++++ cores/bbc/fpga/mist/bbc_mist_top.v | 496 ------------------------- cores/bbc/fpga/mist/data_io.v | 134 ------- cores/bbc/fpga/mist/osd.v | 209 ----------- cores/bbc/fpga/mist/rgb2ypbpr.sv | 55 --- cores/bbc/fpga/mist/sd_card.v | 467 ----------------------- cores/bbc/fpga/mist/user_io.v | 530 --------------------------- 8 files changed, 474 insertions(+), 1906 deletions(-) create mode 100644 cores/bbc/fpga/mist/bbc_mist_top.sv delete mode 100755 cores/bbc/fpga/mist/bbc_mist_top.v delete mode 100644 cores/bbc/fpga/mist/data_io.v delete mode 100644 cores/bbc/fpga/mist/osd.v delete mode 100644 cores/bbc/fpga/mist/rgb2ypbpr.sv delete mode 100644 cores/bbc/fpga/mist/sd_card.v delete mode 100644 cores/bbc/fpga/mist/user_io.v diff --git a/cores/bbc/fpga/mist/bbc_mist_top.qsf b/cores/bbc/fpga/mist/bbc_mist_top.qsf index 4a4f3d7..53c14ba 100644 --- a/cores/bbc/fpga/mist/bbc_mist_top.qsf +++ b/cores/bbc/fpga/mist/bbc_mist_top.qsf @@ -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 \ No newline at end of file diff --git a/cores/bbc/fpga/mist/bbc_mist_top.sv b/cores/bbc/fpga/mist/bbc_mist_top.sv new file mode 100644 index 0000000..fbbd91b --- /dev/null +++ b/cores/bbc/fpga/mist/bbc_mist_top.sv @@ -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 diff --git a/cores/bbc/fpga/mist/bbc_mist_top.v b/cores/bbc/fpga/mist/bbc_mist_top.v deleted file mode 100755 index 2f2e82e..0000000 --- a/cores/bbc/fpga/mist/bbc_mist_top.v +++ /dev/null @@ -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 diff --git a/cores/bbc/fpga/mist/data_io.v b/cores/bbc/fpga/mist/data_io.v deleted file mode 100644 index a3b395e..0000000 --- a/cores/bbc/fpga/mist/data_io.v +++ /dev/null @@ -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 -// -// 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 . -// - -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 diff --git a/cores/bbc/fpga/mist/osd.v b/cores/bbc/fpga/mist/osd.v deleted file mode 100644 index 460fb0d..0000000 --- a/cores/bbc/fpga/mist/osd.v +++ /dev/null @@ -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 -// -// 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 . -// - -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 diff --git a/cores/bbc/fpga/mist/rgb2ypbpr.sv b/cores/bbc/fpga/mist/rgb2ypbpr.sv deleted file mode 100644 index 1e1662e..0000000 --- a/cores/bbc/fpga/mist/rgb2ypbpr.sv +++ /dev/null @@ -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 diff --git a/cores/bbc/fpga/mist/sd_card.v b/cores/bbc/fpga/mist/sd_card.v deleted file mode 100644 index dfd97de..0000000 --- a/cores/bbc/fpga/mist/sd_card.v +++ /dev/null @@ -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 -// -// 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://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< -// -// 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 . -// - -// 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