Brainer: VHDL find-en-fejl

man jan 17, 2011 (Axcon)

Den ny brainer stammer fra noget kode til simulering, som bare ikke opfører sig fornuftigt. Det vil sige det gør jo præcis som det står skrevet, men kan du spotte hvor der mangler noget så det kommer til at virke som tiltænkt?

library ieee;
use ieee.std_logic_1164.all;

entity gizmo is
  port (
    some_control : in std_logic_vector(3 downto 0);
    q : out std_logic);
end entity gizmo;

architecture rtl of gizmo is
begin
  -- Not written yet
end architecture rtl;
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity thingy is
  port (
    d : in std_logic_vector(1 downto 0);
    oe : in std_logic; -- Yes, active high!
    q : out std_logic);
end entity thingy;

architecture rtl of thingy is
  signal q_int : std_logic;
begin
  q_int <= d(0) and d(1);
  q <= q_int when oe = '1' else 'Z';
end architecture rtl;
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity simple_test is
end entity simple_test;

architecture sim of simple_test is
  signal stimulus : unsigned(6 downto 0);
  signal q : std_logic;
begin
  thingy_dut : entity work.thingy
    port map (
      d => std_logic_vector(stimulus(1 downto 0)),
      oe => std_logic(stimulus(2)),
      q => q);

  gizmo_dut : entity work.gizmo
    port map (
      some_control => std_logic_vector(stimulus(6  downto 3)),
      q => q);

  process is
  begin
    stimulus <= (others => '0');
    for i in 0 to 127 loop
      wait for 10 ns;
      stimulus <= stimulus+1;
    end loop;
  end process;
end architecture sim;

Først med et rigtigt svar i kommentarfeltet vinder hele hæderen.

Kommentarer (5)

  1. Karsten added on 17. januar 2011

    Hej, Fejlen ligger her:
    q_int <= d(0) and d(1);
    q <= q_int when oe = '1' else 'Z';

    q_int bliver assignet i line 1 samme tid som den bliver brugt i linie 2, det betyder at q_int er un-assigned når den bruges.

    Løsning:
    Sæt 1ps delay ind mellem linie 1 & 2 eller lad være med at bruge 'temporary' signaler.

  2. Benny Simonsen added on 20. januar 2011

    Det kan være q der har to drivere, hvor det ikke ser ud til at den ene kan tri-states.

    Forøvrigt er det at håbe at gizmo er design top-level, hvis det skal i en FPGA (afh. af værktøj) – ikke alle værktøjer lader tri-state ‘Z’ komme op igennem hirakiporte.

    /Benny

  3. Martin Rønne added on 22. februar 2011

    Benny er inde på noget af det rigtige: q-outputs fra de to instanser er forbundet sammen i testbenchen. Der mangler derfor enten en arbitrering i testbenchen eller en tristate funktion på gizmo, styret af “not stimulus(2)”.

    En anden lille detalje i stimulus processen er, at “stimulus” signalet bliver sat til 127+1 = 128 i den sidste loop, hvor stimulus kun er defineret op til 127. Grunden til at det alligevel går godt er at processen stopper i samme iteration og straks starter forfra og nulstiller “stimulus”. Men det er ikke helt korrekt VHDL.

  4. Thomas added on 22. februar 2011

    For at kunne benytte typen UNSIGNED skal IEEE pakken STD_LOGIC_ARITH bruges. Ønskes dette skal følgende to linjer med i koden:

    library IEEE;
    use IEEE.STD_LOGIC_ARITH.all;

    Er dette fejlen?

    mvh Thomas

  5. Knud added on 24. februar 2011

    Som Benny og Martin skriver, så drives q af både thingy og gizmo. Resultatet dannes af std_logic_1164′s resolution function. Resultatet vil altid være ‘U’, hvis bare et input er ‘U’.
    gizmo “– Not written yet” giver q = ‘U’, så simuleringen viser ikke funktionen af thingy.
    Man kunne i princippet erstatte std_logic_1164′s resolution function, eller man kan åbne q fra gizmo.
    Min foretrukne løsning er dog at give q en weak default i gizmo, q <= 'W', eller 'Z', 'H', 'L'.

Hvad mener du?