MEGA65 / mega65-core

MEGA65 FPGA core
Other
244 stars 88 forks source link

Errors while compiling #39

Closed sorgelig closed 3 years ago

sorgelig commented 7 years ago

https://github.com/MEGA65/mega65-core/blob/c1954d254a64a65d1a05083dcd4cb5262f61ca88/src/vhdl/viciv.vhdl#L1689

is current VHDL can be compiled? I have a lot of issues with signal multi-drivers like on link. For example the address bus palette_fastio_address gets assigned in lines: first group, lines: 1689 1693 1697 second group, lines: 2300 2304 2308 First group is combination logic used in read while second group is sequential logic triggered by rising_edge(ioclock) during write. This produces error as this signal has 2 drivers. I didn't use Xilinx development tools. I use Altera. But i've though there is a common HDL rule where signals might be assigned only in one logical block. There are many such places in the different HDL files. Finally, i found some modules have different signal assignment than calling module.

Overall code doesn't look like working. Am i right?

gardners commented 7 years ago

For the moment, build from the m65pcb-ports branch if not already doing so. This branch synthesises fine using ISE. We will synchronise master and development to this in the near future.

However, it is possible that there may still be problems of this sort when switching tools, due to my inferior VHDL skills and differences in tools. If you can confirm which branch you are using, we can work out if we still need a solution, and proceed from there.

sorgelig commented 7 years ago

I've cloned default branch, which should be master, i guess.

By the way, is it really necessary to use such high resolution? While many TVs/Monitors can support it, for compatibility purpose can you consider 1280x720@60 at least as an option?

gardners commented 7 years ago

Hello,

ok. Try m65pcb-ports and let me know if the problem is still present.

Regarding the resolution, the challenge is we need to use a single common mode that works everywhere, if we are to preserve the C64 idiom of standardised raster timing. That said, we may well move to 800x480 for a variety of reasons I can't presently explain. For testing, you can certainly pick a mode with a lower dot clock to ease your timing closure. It must be an integer multiple of the CPU clock, however.

Paul.

On 27 October 2017 at 15:30, sorgelig notifications@github.com wrote:

I've cloned default branch, which should be master, i guess.

By the way, is it really necessary to use such high resolution? While many TVs/Monitors can support it, for compatibility purpose can you consider 1280x720@60 at least as an option?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-339855478, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT-qvHlKcjS2LM6WlA1HgUIsq_rr8ks5swUBcgaJpZM4QIa4o .

sorgelig commented 7 years ago

Ok. i'm looking into m65pcb-ports branch, but can't find top-level files container*.vhd

sorgelig commented 7 years ago

By the way, can you tell what is current BRAM (FPGA RAM) usage in the project? My FPGA has 5,662,720bits of BRAM - do i have chance to run the mega65?

gardners commented 7 years ago

The m65pcb-ports branch uses a new Makefile that creates all the files required. Also, it uses top-levels named for the different FPGA boards we are using, e.g., nexys4ddr, m65pcbr1 etc.

As for BRAM, we are using almost the entire BRAM of the T100 FPGA. There is some scope to save some space by merging the video and shadow RAM if you dropped the pixel clock (and possibly CPU clock) enough, but that would be a lot of work.

You currently need 128KiB for chip ram, 128KiB for the shadow of that, 128KiB for the "ROM", 32KiB for colour RAM, 24KiB for the Hypervisor and a few other 4KiB and 8KiB buffers here and there.

But if I have calculated correctly, your FPGA has more BRAM than the T100, so it should be fine. What part/board are you using, out of curiosity?

sorgelig commented 7 years ago

If you are still targeting to T100 then it's good! I was afraid you've moved to T200 already.

I'm trying to port mega65 to my project MiSTer: https://github.com/MiSTer-devel/Main_MiSTer/wiki It's based on Terasic DE10-nano with additional expansion boards. Besides the main board all PCB designs, SW and HDL are open source and available on my repository.

I have ported C64, but in some aspects it's desired to be better. That's why i want to try your version of C64 as a subset of mega65.

gardners commented 7 years ago

Ah, very cool. Well, we are happy for the M65 core to be ported, as we very much agree with the open-source approach. Our C64 core is currently not as good as we would like, but welcome improvements, and certainly intend to improve it further. Note at present our CPU defaults to 4510, not 6502. 6502 illegal opcodes are only partly implemented, and indeed the CPU is currently over complex for what it needs to do, and needs some refactoring and simplification -- but maybe not until we have some better test cases, so that we can verify that nothing gets lost in the process. I have started work on a pipelined multi-core register-renaming 4510/6502 that is designed to be a lot faster and smaller in hardware, while still completely backward compatible (including for self-modifying code), but it isn't very far advanced yet.

You can see the current progress at: https://github.com/gardners/gs4502b

gardners commented 7 years ago

convert is a standard unix package for converting image types. apt-get install convert should get it. what OS are you using?

On 27 October 2017 at 18:03, sorgelig notifications@github.com wrote:

where can i get convert utility used in your makefile?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-339873429, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT4iGj34jPrNuQy92ITJQQv9_EelIks5swWQxgaJpZM4QIa4o .

sorgelig commented 7 years ago

i've found it already, sorry :)

now i cannot find m65fdisk.prg is the any link where to download it?

sorgelig commented 7 years ago

I'm using Windows. I've downloaded this https://www.imagemagick.org/script/convert.php it seems the same as linux one.

gardners commented 7 years ago

It is built from a git submodule.

git submodule init git submodule update make

should do everything.

On 27 October 2017 at 18:17, sorgelig notifications@github.com wrote:

i've found it already, sorry :)

now i cannot find m65fdisk.prg is the any link where to download it?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-339875096, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT5vRgKTlEONQQr96p-B5QYcW7RGjks5swWd0gaJpZM4QIa4o .

sorgelig commented 7 years ago

it seems it links to non-existing commit. github gives error 404. git submodule also give error. I will clone the latest commit - hope it will work as well.

gardners commented 7 years ago

I have just pushed the missing commit

On 27 October 2017 at 18:38, sorgelig notifications@github.com wrote:

it seems it links to non-existing commit. github gives error 404. git submodule also give error. I will clone the latest commit - hope it will work as well.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-339877686, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT2-kS3TUP1KSpmyZB3CDOEtO9a7Tks5swWxngaJpZM4QIa4o .

sorgelig commented 7 years ago

Thanks for supporting! I'm slowly moving forward. another problem:

$(BINDIR)/diskmenu_c000.bin:    $(UTILDIR)/diskmenuc000.a65 $(UTILDIR)/diskmenu.a65 $(BINDIR)/etherload.prg
    $(OPHIS) $< -l $*.list -m $*.map -o $*.prg

i see references to diskmenu_c000.bin, but actually diskmenu_c000.prg is produced. Is it mistake in makefile?

sorgelig commented 7 years ago

ok, after changing to

$(OPHIS) $< -l $*.list -m $*.map -o $*.bin

i could finish generate following: generated_vhdl firmware iomap.txt utilities roms

So, now i have files for SD card and hopefully all HDL files. Preparation and adjusting the HDL code will take some time, i think. So will report you later about result.

gardners commented 7 years ago

okay. let me know how you go. Feel free to make a pull request for the fix.

Paul.

On 26 October 2017 at 23:58, sorgelig notifications@github.com wrote:

ok, after changing to

$(OPHIS) $< -l $.list -m $.map -o $*.bin

i could finish generate following: generated_vhdl firmware iomap.txt utilities roms

So, now i have files for SD card and hopefully all HDL files. Preparation and adjusting the HDL code will take some time, i think. So will report you later about result.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-339889644, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT2XWHUuTaApPZNHv75VpHC7-ywvkks5swX8sgaJpZM4QIa4o .

sorgelig commented 7 years ago

it's me again :)

I don't know how Xilinx compiles this part of code:

    if ioclock'event and ioclock = '1' then
      -- Allow writing to bitplane buffer memory directly for debugging
      -- (will be overridden if VIC-IV data pipeline is feeding us data)
      -- @IO:GS $FFBF000 - $FFBFFFF - DEBUG allow writing directly to the bitplane data buffer.  Will be removed in production.
      if fastio_write='1' and fastio_address(19 downto 12) = x"BF" then
        bitplanedatabuffer_waddress(11 downto 0)
          <= fastio_address(11 downto 0);
        bitplanedatabuffer_wdata(8) <= '0';
        bitplanedatabuffer_wdata(7 downto 0) <= fastio_wdata;
        bitplanedatabuffer_write <= '1';
      end if;
    end if;
    if pixelclock'event and pixelclock = '1' then  -- rising clock edge

      -- Copy sprite colission status out
      sprite_map_out <= sprite_map_in;
      sprite_fg_map_out <= sprite_fg_map_in;

      -- Have a drive stage on bitplane mode bits to ease timing.
      bitplane_mode <= bitplane_mode_in;      
      bitplane_enables <= bitplane_enables_in;
      bitplane_complements <= bitplane_complements_in;

      -- copy sprite data chain from input side to output side      
      sprite_spritenumber_out <= sprite_spritenumber_in;
      sprite_datavalid_out <= sprite_datavalid_in;
      sprite_bytenumber_out <= sprite_bytenumber_in;
      sprite_data_out <= sprite_data_in;
      sprite_number_for_data_out <= sprite_number_for_data_in;

      if sprite_datavalid_in = '1' and (sprite_spritenumber_in > 7) then
        -- Record sprite data
        report "BITPLANES:"
          & "  byte $" & to_hstring(sprite_data_in)
          & " from VIC-IV for bp#"
          & integer'image(sprite_spritenumber_in)
          & " byte #" & integer'image(sprite_bytenumber_in)
          & " x=" & integer'image(x_in)
          & " x_start=" & integer'image(bitplane_x_start)
          & " y=" & integer'image(y_in)
          & " y_start=" & integer'image(bitplane_y_start)
          & " border_in=" & std_logic'image(border_in)
          & " bitplane_mode_in=" & std_logic'image(bitplane_mode_in)
          & " bitplane_drawing=" & std_logic'image(bitplane_drawing);
        bitplanedatabuffer_waddress(11 downto 9)
          <= to_unsigned(sprite_spritenumber_in mod 8, 3);
        bitplanedatabuffer_waddress(8 downto 0)
          <= to_unsigned(sprite_bytenumber_in, 9);
        bitplanedatabuffer_wdata(8) <= '0';
        bitplanedatabuffer_wdata(7 downto 0) <= sprite_data_in;
        bitplanedatabuffer_write <= '1';
      end if;      

signals bitplanedatabuffer_wdata and bitplanedatabuffer_write are driven by 2 clocks ioclock and pixelclock at the same time. Altera tools refuse to synthesize this. It's even impossible in real world. It's like connect outputs of 2 clocks together physically. How it's possible in Xilinx - i have no idea :(

sorgelig commented 7 years ago

in this particular case, these signals are used to write into 2-port RAM, so it would be better to re-arrange the ports. One port use for ioclock control, another for pixelclock control. Anyway, it's not good to clock the RAM port with one clock but drive signal from other clock.

But there are several places with multi-drivers in other parts of code.

gardners commented 7 years ago

Hello,

You can simply remove the ioclock access in the above case, as it was only ever there to help debug bitplane function. Falk Rehwagen will be merging in the final fixes for the bitplanes when he has time, so there is no need to keep the debug function.

Let's just work through the multi-drivers one by one, if that suits you.

Paul.

On 27 October 2017 at 10:41, sorgelig notifications@github.com wrote:

in this particular case, these signals are used to write into 2-port RAM, so it would be better to re-arrange the ports. One port use for ioclock control, another for pixelclock control. Anyway, it's not good to clock the RAM port with one clock but drive signal from other clock.

But there are several places with multi-drivers in other parts of code.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340037628, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonTyFocHV9Gke5Z2qUkpi1SLnhEMQcks5swhW4gaJpZM4QIa4o .

sorgelig commented 7 years ago

Yep, doing one by one is the best way.

    if fastio_read='1' then
      if fastio_addr = x"D3632" then
        -- @IO:GS $D632 - Lower 8 bits of thumbnail buffer read address (TEMPORARY DEBUG REGISTER)
        fastio_rdata <= thumbnail_read_address(7 downto 0);
      elsif fastio_addr = x"D3631" then
        -- @IO:GS $D631 - Read port for thumbnail generator
        fastio_rdata <= thumbnail_rdata;
      elsif fastio_addr = x"D3630" then
        -- @IO:GS $D630-$D631 - Read-only hardware-generated thumbnail of display (accessible only in hypervisor mode)
        -- @IO:GS $D630 - Write to reset port address for thumbnail generator
        -- @IO:GS $D630 - Read to obtain status of thumbnail generator.
        -- @IO:GS $D630.7 - Thumbnail is valid if 1.  Else there has not been a complete frame since elapsed without a trap to hypervisor mode, in which case the thumbnail may not reflect the current process.
        -- @IO:GS $D630.6 - Thumbnail drawing was in progress.
        thumbnail_read_address <= (others => '0');
        fastio_rdata(7) <= thumbnail_valid;
        fastio_rdata(6) <= thumbnail_started;
        fastio_rdata(5 downto 0) <= (others => '0');
      else
        fastio_rdata <= (others => 'Z');
      end if;
    else
      fastio_rdata <= (others => 'Z');
    end if;

    if rising_edge(ioclock) then

      -- Tell ethernet controller which half of the buffer we are writing to.
      -- Ethernet controller autonomously sends the contents of the other half
      -- whenever we switch halves.
      buffer_moby_toggle <= output_address_internal(11);

      -- Logic to control port address for thumbnail buffer
      if fastio_read='1' then
        if fastio_addr = x"D3631" then
          last_access_is_thumbnail <= '1';
          if last_access_is_thumbnail = '0' then
            thumbnail_read_address <= thumbnail_read_address + 1;
          end if;
        else
          last_access_is_thumbnail <= '0';
        end if;       
      else
        last_access_is_thumbnail <= '0';
      end if;             
    end if;

thumbnail_read_address has multi-drivers because first block is combination logic while second block is sequential clocked by ioclock.

sorgelig commented 7 years ago

may be add following code to the ioclock block and remove thumbnail_read_address from combination block?

      elsif fastio_addr = x"D3630" then
        thumbnail_read_address <= (others => '0');
      end if;
sorgelig commented 7 years ago

here is the whole block with my modification:

    if fastio_read='1' then
      if fastio_addr = x"D3632" then
        -- @IO:GS $D632 - Lower 8 bits of thumbnail buffer read address (TEMPORARY DEBUG REGISTER)
        fastio_rdata <= thumbnail_read_address(7 downto 0);
      elsif fastio_addr = x"D3631" then
        -- @IO:GS $D631 - Read port for thumbnail generator
        fastio_rdata <= thumbnail_rdata;
      elsif fastio_addr = x"D3630" then
        -- @IO:GS $D630-$D631 - Read-only hardware-generated thumbnail of display (accessible only in hypervisor mode)
        -- @IO:GS $D630 - Write to reset port address for thumbnail generator
        -- @IO:GS $D630 - Read to obtain status of thumbnail generator.
        -- @IO:GS $D630.7 - Thumbnail is valid if 1.  Else there has not been a complete frame since elapsed without a trap to hypervisor mode, in which case the thumbnail may not reflect the current process.
        -- @IO:GS $D630.6 - Thumbnail drawing was in progress.
        fastio_rdata(7) <= thumbnail_valid;
        fastio_rdata(6) <= thumbnail_started;
        fastio_rdata(5 downto 0) <= (others => '0');
      else
        fastio_rdata <= (others => 'Z');
      end if;
    else
      fastio_rdata <= (others => 'Z');
    end if;

    if rising_edge(ioclock) then

      -- Tell ethernet controller which half of the buffer we are writing to.
      -- Ethernet controller autonomously sends the contents of the other half
      -- whenever we switch halves.
      buffer_moby_toggle <= output_address_internal(11);

      -- Logic to control port address for thumbnail buffer
      if fastio_read='1' then
        if fastio_addr = x"D3631" then
          last_access_is_thumbnail <= '1';
          if last_access_is_thumbnail = '0' then
            thumbnail_read_address <= thumbnail_read_address + 1;
          end if;
        else
          last_access_is_thumbnail <= '0';
        end if;       
        if fastio_addr = x"D3630" then
          thumbnail_read_address <= (others => '0');
        end if;
      else
        last_access_is_thumbnail <= '0';
      end if;             
    end if;
sorgelig commented 7 years ago

another multi-driver:

    if rising_edge(pixelclock) then

      if rx_clear_flags='1' then
        -- Clear byte read flag
        reg_status0_rx_full <= '0';
        -- Clear RX over-run flag
        reg_status1_rx_overrun <= '0';
        -- Clear RX parity error flag
        reg_status2_rx_parity_error <= '0';
        -- Clear RX framing error flag
        reg_status3_rx_framing_error <= '0';
      end if;

      if (baud_subcounter + baud_subcounter_step < 1048576) then
        baud_subcounter <= baud_subcounter + baud_subcounter_step;
        tick709375 <= '0';
      else
        baud_subcounter <= baud_subcounter + baud_subcounter_step - 1048576;

        -- One baud divisor tick has elapsed.
        -- Based on TX and RX modes, take the appropriate action.
        -- Each tick here is 1/2 a bit.
        tick709375 <= '1';
      end if;
      if tick709375='1' or clock709375='0' then
        -- Depending on whether we are running from the 7.09375MHz
        -- clock or the 193.5MHz pixel clock, see if we are at a baud tick
        -- (193.5MHz clock is used for baud rates above 57.6K.)
        fine_tick <= '1';
      else
        fine_tick <= '0';
      end if;
      if fine_tick='1' then
        if reg_tick_countdown > 0 then
          reg_tick_countdown <= reg_tick_countdown - 1;
          baud_tick <= '0';
        else
          reg_tick_countdown <= reg_divisor;
          baud_tick <= '1';
        end if;
      end if;

      -- Keep track of last 16 samples, and update RX value accordingly.
      -- We require consensus to switch between 0 and 1
      rx_samples(15 downto 1) <= rx_samples(14 downto 0);
      rx_samples(0) <= uart_rx;
      if rx_samples = "1111111111111111" then
        filtered_rx <= '1';
      end if;
      if rx_samples = "0000000000000000" then
        filtered_rx <= '0';
      end if;

      if baud_tick = '1' then
        -- Here we have a clock tick that is 7.09375MHz/reg_divisor
        -- (or 193.5MHz/reg_divisor if clock709375 is not asserted).
        -- So we now have a clock which is the target baud rate.
        -- XXX We should adjust our timing position to try to match the phase
        -- of the sender, but we aren't doing that right now. Instead, we will
        -- use the simple consensus filtered RX signal, and just read it.

        -- Progress TX state machine
        uart_tx <= '1';
        if tx_in_progress = '0' and reg_status6_tx_empty='0' and reg_ctrl7_tx_enable='1' then
          -- Sent stop bit
          uart_tx <= '0';
          tx_in_progress <= '1';
          tx_bits_to_send <= 8 - to_integer(reg_ctrl23_char_length_deduct);
          tx_buffer <= reg_data_tx;
          reg_status6_tx_empty <= '1';
        end if;
        if tx_in_progress='1' then
          if tx_bits_to_send > 0 then
            uart_tx <= tx_buffer(0);
            tx_buffer(6 downto 0) <= tx_buffer(7 downto 1);
            tx_bits_to_send <= tx_bits_to_send - 1;
          else
            -- Stop bit
            -- XXX We don't support parity
            uart_tx <= '0';
            tx_stop_bit_sent <= '1';
          end if;
          if tx_stop_bit_sent = '1' then
            tx_in_progress <= '0';
            tx_stop_bit_sent <= '0';
          end if;
        end if;

        -- Progress RX state machine
        if rx_in_progress='0' then
          -- Not yet receiving a byte, so see if we see something interesting
          if filtered_rx='0' and reg_ctrl6_rx_enable='1' then
            -- Start bit
            rx_buffer <= (others => '1');
            rx_in_progress <= '1';
            rx_bits_remaining <= 8 - to_integer(reg_ctrl23_char_length_deduct);
          end if;
        else
          -- Receiving data, parity and/or stop bit
          if rx_bits_remaining > 0 then
            -- Receive next bit
            rx_buffer(6 downto 0) <= rx_buffer(7 downto 1);
            rx_buffer(7) <= filtered_rx;
            rx_bits_remaining <= rx_bits_remaining - 1;
          else
            -- Receive stop bit (or parity when we support it)
            rx_in_progress <= '0';
            -- Stop bit:
            if filtered_rx='0' then
              -- Received byte
              reg_status0_rx_full <= '1';
              if reg_status0_rx_full = '1' then
              end if;
              -- Allow short bytes
              case reg_ctrl23_char_length_deduct is
                when "01" => reg_data_rx(6 downto 0) <= rx_buffer(7 downto 1);
                             reg_data_rx(7) <= '1';
                when "10" => reg_data_rx(5 downto 0) <= rx_buffer(7 downto 2);
                             reg_data_rx(7 downto 6) <= (others => '1');
                when "11" => reg_data_rx(4 downto 0) <= rx_buffer(7 downto 3);
                             reg_data_rx(7 downto 5) <= (others => '1');
                when others => reg_data_rx <= rx_buffer;
              end case;
              -- XXX Work out parity and set state for reading it.
            else
              -- Framing error
              reg_status3_rx_framing_error <= '1';
              -- Make bad data visible, purely for debug purposes
              reg_data_rx <= rx_buffer;
            end if;
            -- XXX Assert IRQ and/or NMI according to RX interrupt masks
          end if;
        end if;
      end if;
    end if;

    if rising_edge(cpuclock) then

      porth_write_strobe <= '0';

      register_number(7 downto 5) := "000";
      register_number(4 downto 0) := fastio_address(4 downto 0);

      -- Calculate read value for various ports
      reg_porte_read <= ddr_pick(reg_porte_ddr,porte,reg_porte_out);        
      reg_portf_read <= ddr_pick(reg_portf_ddr,portf,reg_portf_out);
      reg_portg_read <= ddr_pick(reg_portg_ddr,portg,reg_portg_out);

      -- Support proper tri-stating on port F and port G which connects to FPGA board PMOD
      -- connector.
      for bit in 1 to 7 loop
        -- Bit 0 of porte is the capslock key, which is input only
        if reg_porte_ddr(bit)='1' then
          porte(bit) <= reg_porte_out(bit) or (not reg_porte_ddr(bit));
        else
          porte(bit) <= 'Z';
        end if;
      end loop;
      for bit in 0 to 7 loop
        if reg_portf_ddr(bit)='1' then
          portf(bit) <= reg_portf_out(bit) or (not reg_portf_ddr(bit));
        else
          portf(bit) <= 'Z';
        end if;
        if reg_portg_ddr(bit)='1' then
          portg(bit) <= reg_portg_out(bit) or (not reg_portg_ddr(bit));
        else
          portg(bit) <= 'Z';
        end if;
      end loop;

      -- Check for register writing
      if (fastio_write='1') and (fastio_address(19 downto 16) = x"D")
         and (fastio_address(11 downto 5) = "0110000") then
        register_number(7 downto 5) := "000";
        register_number(4 downto 0) := fastio_address(4 downto 0);
        case register_number is
          when x"00" =>
            reg_data_tx <= std_logic_vector(fastio_wdata);
            reg_status5_tx_eot <= '0';
            reg_status6_tx_empty <= '0';
          when x"01" => null;
          when x"02" =>
            reg_ctrl0_parity_even <= fastio_wdata(0);
            reg_ctrl1_parity_enable <= fastio_wdata(1);
            reg_ctrl23_char_length_deduct  <= fastio_wdata(3 downto 2);
            reg_ctrl45_sync_mode_flags <= std_logic_vector(fastio_wdata(5 downto 4));
            reg_ctrl6_rx_enable <= fastio_wdata(6);
            reg_ctrl7_tx_enable <= fastio_wdata(7);
          when x"03" => reg_divisor(7 downto 0) <= fastio_wdata;
          when x"04" => reg_divisor(15 downto 8) <= fastio_wdata;
          when x"05" => reg_intmask <= std_logic_vector(fastio_wdata);
          when x"06" =>
            -- reg_intflag
            -- This register is not used in the C65 ROM, so we don't know how it
            -- should behave.  What is clear, is that there is some other mechanism
            -- besides reading this register that actually clears the IRQ.
            -- Perhaps just reading the data register is enough to clear an RX
            -- IRQ?  What about TX ready IRQ? It seems like writing a character
            -- or disabling the transmitter should clear it.
          when x"07" => reg_porte_out<=std_logic_vector(fastio_wdata(7 downto 0));
          when x"08" => reg_porte_ddr<=std_logic_vector(fastio_wdata(7 downto 0));

          when x"09" =>
            clock709375 <= fastio_wdata(0);
          when x"0b" => reg_portf_out <= std_logic_vector(fastio_wdata);
          when x"0c" => reg_portf_ddr <= std_logic_vector(fastio_wdata);
          when x"0d" => reg_portg_out <= std_logic_vector(fastio_wdata);
          when x"0e" => reg_portg_ddr <= std_logic_vector(fastio_wdata);
          when x"10" => porth_write_strobe <= '1';
          when x"11" => null; -- bucky keys readonly
          when x"12" =>
            widget_enable_internal <= std_logic(fastio_wdata(0));
            ps2_enable_internal <= std_logic(fastio_wdata(1));
            physkey_enable_internal <= std_logic(fastio_wdata(2));
            virtual_enable_internal <= std_logic(fastio_wdata(3));
            joy_enable_internal <= std_logic(fastio_wdata(4));
          when x"14" => portj_out <= std_logic_vector(fastio_wdata);
                        portj_internal <= std_logic_vector(fastio_wdata);
          when x"15" =>
            portk_internal <= std_logic_vector(fastio_wdata);
          when x"16" =>
            portl_internal <= std_logic_vector(fastio_wdata);
          when x"17" =>
            portm_internal <= std_logic_vector(fastio_wdata);
          when x"18" =>
            portn_internal <= std_logic_vector(fastio_wdata);
          when x"19" =>
            porto_internal <= std_logic_vector(fastio_wdata);
          when x"1A" =>
            portp_internal <= std_logic_vector(fastio_wdata);
          when others => null;
        end case;
      end if;
    end if;

reg_status6_tx_empty is driven by pixelclock and cpuclock. If pasting the code is not convenient for you, i will write the file name and line number instead.

gardners commented 7 years ago

Hello,

The thumbnail_read_address <= (others => '0') is to reset the read pointer for the thumbnail buffer. Currently this happens if $D630 is READ. It could be easily changed to be reset instead when $D630 is WRITTEN, which would then place it in the ioblock. This is more or less what you are proposing, so it should be okay.

Paul.

On 27 October 2017 at 12:48, sorgelig notifications@github.com wrote:

may be add following code to the ioclock block and remove thumbnail_read_address from combination block?

  elsif fastio_addr = x"D3630" then
    thumbnail_read_address <= (others => '0');
  end if;

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340068689, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT7gPWpgJRmWTxv0kxAd-Ua0P1Lafks5swjOegaJpZM4QIa4o .

sorgelig commented 7 years ago

ok. what about reg_status6_tx_empty?

gardners commented 7 years ago

That one is a bit trickier, as the TX buffer can be cleared either by the FSM, or via writing to the register. Perhaps make one of them create a strobe or toggle that the other can read, to actually clear it?

Paul.

On 27 October 2017 at 13:24, sorgelig notifications@github.com wrote:

ok. what about reg_status6_tx_empty?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340076414, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonTxW7U6MB_fKEmMJAK6Yq_WC8TGeAks5swjv2gaJpZM4QIa4o .

sorgelig commented 7 years ago

i think i won't use UART on my mega65 port, so i can simply remove reg_status6_tx_empty assignment in one of these blocks. Actually i don't know what's relation between UART and pixel clock. Probably pixel clock is used as a master clocking for UART counters. I think, the whole UART should be transferred to a single clock which should be cpuclock. And the problem will be fixed.

sorgelig commented 7 years ago

You've said above that pixelclock should be multiple to cpu clock. So, i suggest to move the whole project to single clock. It can be a master clock which will be multiple to pixel clock, cpu clock and io clock. So, it will be some clock, with several clock enablers ce_cpu, ce_pixel, ce_io. And in this case it will be easy to migrate from one virtual clock to another between blocks. you can check my ZX core code: https://github.com/MiSTer-devel/ZX-Spectrum_MISTer/blob/master/zxspectrum.sv see ce_* signal generation and usage there. It's pretty common technique in HDL.

sorgelig commented 7 years ago

By the way, what is role of ena signal in Xilinx BRAM megafunction? Is it clock enabler or output enabler?

gardners commented 7 years ago

Hello,

I did warn you that my VHDL is not that great ;)

Paul.

On 27 October 2017 at 12:55, sorgelig notifications@github.com wrote:

here is the whole block with my modification:

if fastio_read='1' then
  if fastio_addr = x"D3632" then
    -- @IO:GS $D632 - Lower 8 bits of thumbnail buffer read address (TEMPORARY DEBUG REGISTER)
    fastio_rdata <= thumbnail_read_address(7 downto 0);
  elsif fastio_addr = x"D3631" then
    -- @IO:GS $D631 - Read port for thumbnail generator
    fastio_rdata <= thumbnail_rdata;
  elsif fastio_addr = x"D3630" then
    -- @IO:GS $D630-$D631 - Read-only hardware-generated thumbnail of display (accessible only in hypervisor mode)
    -- @IO:GS $D630 - Write to reset port address for thumbnail generator
    -- @IO:GS $D630 - Read to obtain status of thumbnail generator.
    -- @IO:GS $D630.7 - Thumbnail is valid if 1.  Else there has not been a complete frame since elapsed without a trap to hypervisor mode, in which case the thumbnail may not reflect the current process.
    -- @IO:GS $D630.6 - Thumbnail drawing was in progress.
    fastio_rdata(7) <= thumbnail_valid;
    fastio_rdata(6) <= thumbnail_started;
    fastio_rdata(5 downto 0) <= (others => '0');
  else
    fastio_rdata <= (others => 'Z');
  end if;
else
  fastio_rdata <= (others => 'Z');
end if;

if rising_edge(ioclock) then

  -- Tell ethernet controller which half of the buffer we are writing to.
  -- Ethernet controller autonomously sends the contents of the other half
  -- whenever we switch halves.
  buffer_moby_toggle <= output_address_internal(11);

  -- Logic to control port address for thumbnail buffer
  if fastio_read='1' then
    if fastio_addr = x"D3631" then
      last_access_is_thumbnail <= '1';
      if last_access_is_thumbnail = '0' then
        thumbnail_read_address <= thumbnail_read_address + 1;
      end if;
    else
      last_access_is_thumbnail <= '0';
    end if;
    if fastio_addr = x"D3630" then
      thumbnail_read_address <= (others => '0');
    end if;
  else
    last_access_is_thumbnail <= '0';
  end if;
end if;

Actually the part with combination logic may introduce glitches in work since it produces many latches. Latches are evils :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340070130, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT95HWfH4--UHRCF8XbZaQk0ZfERjks5swjUhgaJpZM4QIa4o .

gardners commented 7 years ago

Hello,

I will freely confess that I don't understand the implications of this, particularly whether it constrains timing closure of all components to the full clock rate. The current CPU cannot operate at the pixelclock speed (in fact, it currently doesn't quite meet timing closure at its current speed).

Paul.

On 27 October 2017 at 19:22, sorgelig notifications@github.com wrote:

You've said above that pixelclock should be multiple to cpu clock. So, i suggest to move the whole project to single clock. It can be a master clock which will be multiple to pixel clock, cpu clock and io clock. So, it will be some clock, with several clock enablers ce_cpu, ce_pixel, ce_io. And in this case it will be easy to migrate from one virtual clock to another between blocks. you can check my ZX core code: https://github.com/MiSTer- devel/ZX-SpectrumMISTer/blob/master/zxspectrum.sv see ce* signal generation and usage there. It's pretty common technique in HDL.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340133166, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT3V2_dyh_rHHmf1gxfC0t_-8bl3Hks5swo_UgaJpZM4QIa4o .

sorgelig commented 7 years ago

I think, if you go down in screen resolution to something like 640x480@60, then pixel clock will be low. Neither C64 nor C65 had 1920x1200, so there is no point to climb so high with very high clock rates. The core will have relaxed time as well. So, the whole project will be clocked by single clock around 50MHz, then you will see how easy you can code it. And you won't need to think about crossing the clock domains which will help to shorten the time in some critical places.

I've managed to compile HDL finally. When core starts it access the SD card and seems read something couple times. Screen displays some misty green frame in the upper part.

gardners commented 7 years ago

Hello,

From memory it is output enable.

Paul.

On 27 October 2017 at 19:48, sorgelig notifications@github.com wrote:

By the way, what is role of ena signal in Xilinx BRAM megafunction? Is it clock enabler or output enabler?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340134354, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT0vNslD_SVhwlE7SKR5ARjnm3I5Xks5swpXmgaJpZM4QIa4o .

gardners commented 7 years ago

Hello,

Well done on getting it to synthesise.

Regarding resolution, we had purposely wanted the M65 to be capable of higher resolutions. That said, as I mentioned, it is likely that we will go to 800x480, as it allows for some side and top borders, while still allowing a slower clock -- but this is still a bit up in the air. A faster pixel clock allows more sprites etc, as the VIC-IV has more time to fetch things.

Paul.

On 27 October 2017 at 21:25, sorgelig notifications@github.com wrote:

I think, if you go down in screen resolution to something like 640x480@60, then pixel clock will be low. either C64 nor C65 had 1920x1200, so there is no point to climb so high with very high clock rates. The core will have relaxed time as well. So, the whole project will be clocked by single clock around 50MHz, then you will see how easy you can code it. And you won't need to think about crossing the clock domains which will help to shorten the time in some critical places.

I've managed to compile HDL finally. When core starts it access the SD card and seems read something couple times. Screen displays some misty green frame in the upper part.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/MEGA65/mega65-core/issues/39#issuecomment-340138281, or mute the thread https://github.com/notifications/unsubscribe-auth/AAonT6G0GVkuYncserchDKRJiRXqoqw2ks5swqyqgaJpZM4QIa4o .