maximb

Members
  • Content Count

    7
  • Joined

  • Last visited

Posts posted by maximb

  1. Hi All, I just wanted to say that I'm also really struggling to get any kind of TFTP boot going on the Zynq, but not with other devices that I have.

    I have another ARM-based SBC computer, the S805X "La Frite" Librecomputer, which also boots via U-boot. I connected its ethernet port to a physical internal network consisting of a switch and a router (Router is the "HAp ac lite" from MikroTik), which is running DHCP. I connect my laptop to it running TFTP server, and is serving a very dumb "test.txt" file consisting of 16 bytes.

    I can load it from the La Frite librecomputer by simply setting the "serverip", "ipaddr" and "netmask" variables, and then issuing the "loadaddr 0x30000000 test.txt" command, and sure enough it fetches my 16 bytes from the server.

    But I cannot do the same with the Zynq board. I know the network works, and the server works, because I got the librecomputer to behave. But the Zynq just gets stuck on "Can't ping server".

  2. Hi everyone, I am using a ZedBoard, and following this guide:

    https://www.xilinx.com/support/documentation/sw_manuals/xilinx2020_1/ug1165-zynq-embedded-design-tutorial.pdf

    I succesfully got to Chapter 2, where I can do the following:

    • Create Zynq block design
    • Export hardware file (.xsa)
    • Use Vitis to create a "standalone hardware platform" using this file
    • Use Vitis to create a Hello World application
    • Debug this application, and I can see "Hello World" printed in Vitis serial monitor over the UART cable.

    However, I would like to progress to running Petalinux, and went to Chapter 6. Here I get stuck once I issue "bootm 0x30000000" command to U-boot (as per tutorial), where U-boot prints "Starting kernel...", and nothing appears afterwards.

    I've made a 3:00 video showing that although the "Hello World" application works, the Petalinux loading procedure does not. You can view it here:

    https://www.youtube.com/watch?v=mkPxveyynIg

    I am happy to provide any more information. Using Vivado 2020.1, and Vitis 2020.1. I tried the following:

    • Re-build Petalinux
    • Re-build Petalinux, reconfigure kernel to enable early printk and serial wire over Zynq UART
    • Re-build Petalinux, and disable Xilinx Zynq GPIO drivers (An answer on the Xilinx community forums suggested this may be the cause).

    I am using the BSP package for the ZED BSP (MD5 SUM Value : f7f63769ea9feeb36b460d4e5988a5de) from here: https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/embedded-design-tools.html

    Unfortunately none of these worked. Any help appreciated!

  3. Hi, I recently discovered that the wrong scan codes are sent for certain keys.

    This is tested with my own PS2 keyboard controller, and the same behaviour is present with the official demo: https://reference.digilentinc.com/learn/programmable-logic/tutorials/nexys-4-ddr-keyboard-demo/start

    I have tested two keyboards: One Logitech K120, and one Microsoft comfort curve 3000. The following behaviour is exhibited:

    Left arrow set 2 scancode should be: E0 6B / E0 F0 6B. Actual: 6B / F0 6B

    Up arrow set 2 scancode should be: E0 75 / E0 F0 75. Actual: 75 / F0 75

    Down arrow set 2 scancode should be: E0 72 / E0 F0 72. Actual: 72 / F0 72

    Curiously, the right arrow scancode is correct.

    Numpad division set 2 scancode should be: E0 4A / E0 F0 4A. Actual: 4A / F0 4A

    Can anyone confirm?

    Online Documentation for Altium Products - PS2 Keyboard Scan Codes - 2017-09-13.pdf

  4. Hi, I am in the process of developing my own DDR2 controller as an exercise. Consequently, I'm trying to avoid using tools like MIG.

    Unfortunately I could not fully escape the clutches of automated tools, as in order to correctly configure the .xdc constraints file, I've had to have a peek at the following .prj file generated by the MIG in the official Digilent DDR2 Demo implementation: https://github.com/Digilent/Nexys-4-DDR-OOB/blob/master/src/ip/ddr/mig.prj

    I interpret the following line: "<InternalVref>1</InternalVref>" as setting the INTERNAL_VREF property to 1V. Therefore, I add the following line in my .xdc file:

    set_property INTERNAL_VREF 1 [get_iobanks 34]

    However, this configuration fails to implement for the Nexys4 DDR chip with the following error:

    [DRC 23-20] Rule violation (IVREF-2) INTERNAL_VREF - Bank 34 has INTERNAL_VREF set to an unsupported value (1.000V).  Supported VREF values for this part are:
    0.600,
    0.675,
    0.750,
    0.900.

    Which value should I choose to use?

  5. Hi,

    I am using Vivado 2016.4 to program the Nexys4 DDR 7-segment display.

    I have a very simple VHDL project, which works as follows:

    • 100 MHz clock is used to increment an 8-bit counter
    • when this counter overflows, it inverts the value of a local signal called "slowclk". Hence, "slowclk" is "clk" divided by 512.
    • the "slowclk" is used to increment another 8-bit counter, the output of which is assigned to the 7-segment display segment selector pins on the board.

    Complete VHDL source:

    Spoiler

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;

     

    entity segdisp is

        port (    clk    : in    std_logic;
            seg_en    : out    std_logic_vector(7 downto 0);
            seg_cs    : out    std_logic_vector(7 downto 0) );
    end;

    architecture top of segdisp is
        signal r_count: natural range 0 to 255 := 0;
        signal disp_next: std_logic := '0';

        signal seg_cs_int: natural range 0 to 255;

        signal clkdiv: natural range 0 to 255 := 0;
        signal slowclk: std_logic := '0';
        
        function int2slv(arg: integer; length: positive) return std_logic_vector is
        begin
            return std_logic_vector(to_unsigned(arg, length));
        end function;
    begin
        seg_cs <= int2slv(seg_cs_int, seg_cs'length);
        seg_en <= not X"80";

        divider: process (clk)
        begin
            if rising_edge(clk) and clk = '1' then
                if clkdiv = 255 then
                    clkdiv <= 0;
                    slowclk <= not slowclk;
                else
                    clkdiv <= clkdiv + 1;
                end if;
            end if;
        end process;

        main: process (slowclk)
        begin
            if rising_edge(slowclk) and slowclk = '1' then
                seg_cs_int <= seg_cs_int + 1;
            end if;
        end process;
        
    end architecture top;

    Note: I understand that given such division, the effect on the digit segments will still not be visible - I just want to demonstrate the timing problem.

    However, the design fails to meet timing constraints as follows in attached pictures:

    G35bJhG.png

    k2yITaN.png

    Timing constraint failures in more detail, including the full source VHDL:

    G7Wd4Hb.png

    Clock routing on the FPGA:

    jOSAD62.png

    The following is the .xdc constraints file (commented-out definitions are omitted):

    Spoiler

     

    ## Clock signal
    set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports { clk }]
    create_clock -add -name sys_clk_pin -period 10.00 -waveform {0.000 5.000} [get_ports { clk }]

    ...

    set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {seg_cs[7]}]
    set_property -dict {PACKAGE_PIN R10 IOSTANDARD LVCMOS33} [get_ports {seg_cs[6]}]
    set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports {seg_cs[5]}]
    set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports {seg_cs[4]}]
    set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {seg_cs[3]}]
    set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports {seg_cs[2]}]
    set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports {seg_cs[1]}]

    set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports {seg_cs[0]}]

    set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports {seg_en[0]}]
    set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {seg_en[1]}]
    set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports {seg_en[2]}]
    set_property -dict {PACKAGE_PIN J14 IOSTANDARD LVCMOS33} [get_ports {seg_en[3]}]
    set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {seg_en[4]}]
    set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {seg_en[5]}]
    set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {seg_en[6]}]
    set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {seg_en[7]}]

    ...

    set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
    set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
    set_property CONFIG_MODE SPIx4 [current_design]

    set_property CFGBVS VCCO [current_design]
    set_property CONFIG_VOLTAGE 3.3 [current_design]

     

    From what little I know about FPGA clock routing and resources, I understand this to be due to the high-frequency clock and associated logic being in different regions to each other, thus requiring the implementation run to route the clock signal through awkward paths; as a consequence, the total signal propagation time is such, that before the logic relevant to the current clock pulse is evaluated, the next clock front is already present.

    Am I correct in this thinking? And in either case, how can I fix the timing issues that Vivado warns about?