VHDL-Fehler: Mehrere konstante Treiber für net

Ich kann nicht finden, wie ich mit dem Fehler umgehen soll: "mehrere konstante Laufwerke", der auftritt, wenn ich versuche, dasselbe Netz in einem einzigen Vorgang zu lesen und einzustellen.

Ich muss den "Ausgang" für einige Taktzyklen auf die steigende Flanke des "enable"-Eingangs setzen und dann den "Ausgang" zurücksetzen. Mein Code:

library ieee;
use ieee.std_logic_1164.all;

entity trigger_slave is
    generic (
        OUT_ON_PERIOD   : integer := 10 - 1                                 
    );
    port (
        enable          : in std_logic; 
        clk_1MHz        : in std_logic;                                                                         
        OUTPUT          : buffer std_logic                           
    );
end trigger_slave;

architecture behavior of trigger_slave is

begin   
    process (enable)
    begin
        if (rising_edge(enable)) then
            OUTPUT <= '1';
        end if;
    end process;

    process (clk_1MHz)  
        variable counter        : integer range 0 to OUT_ON_PERIOD := 0;
    begin
        if (rising_edge(clk_1MHz) and OUTPUT = '1') then        -- here is the problem!
            if (counter = OUT_ON_PERIOD) then
                counter := 0;
                OUTPUT <= '0';
            else 
                counter := counter + 1;
                OUTPUT <= '1';
            end if;         
        end if;
    end process;

end behavior;

Bitte helfen Sie mir mit diesem Code. Vielen Dank.

Was genau versuchst du zu erreichen? Es sieht so aus, als ob Sie versuchen, etwas zu tun, das auf eine schwierige Weise einfach ist. Ist das nicht nur ein einfacher Zähler?
Ja, vielleicht ist es einfach, aber ich bin ein Anfänger. Es ist eine Art Zähler, der mit einer externen Uhr getriggert wird
Du meinst, enableist eine andere Uhr?

Antworten (2)

Ich weiß, dass Sie ein Anfänger sind, aber Ihre VHDL liest sich so, als würden Sie versuchen, ein Computerprogramm zu schreiben, und keine digitale Logikschaltung entwerfen.

Informieren Sie sich im Internet über synchrones digitales Logikdesign.

Dann informieren Sie sich danach über VHDL und sehen Sie sich an, wie es die gewünschte Schaltung implementieren kann. Denken Sie daran: Das Schaltungsdesign (egal wie umfassend) steht an erster Stelle, das VHDL-Design an zweiter Stelle.

In der Zwischenzeit ist hier das gewünschte Design. (Ich habe es nicht mit ModelSim kompiliert, daher könnten Tippfehler enthalten sein.)

library ieee;
use ieee.std_logic_1164.all;

entity TRIGGER_SLAVE is
  generic(
    OUT_ON_PERIOD                 : integer := 10 - 1
  );
  port(
    CLK                           : in  std_logic;
    RST                           : in  std_logic;
    ENABLE                        : in  std_logic;
    OUTPUT                        : out std_logic
  );
end entity TRIGGER_SLAVE;

architecture behaviour of TRIGGER_SLAVE is
  signal delayCtr                 : natural range 0 to OUT_ON_PERIOD;
  signal enableOld1               : std_logic;

begin

  pDelay : process(RST, CLK) is
  begin
    if (RST = '1') then
      delayCtr    <=   0 ;
      enableOld1  <=  '0';
      OUTPUT      <=  '0';`

    elsif rising_edge(CLK) then

      -- Keep old enable level from 1 CLK ago, for edge detection.
      enableOld1  <=  ENABLE;

      -- Reload delay counter on ENABLE rising edge then run it down to zero.
      if (ENABLE = '1' and enableOld1 = '0') then
        delayCtr  <=  OUT_ON_PERIOD;

      elsif (delayCtr /= 0) then
        delayCtr  <=  delayCtr - 1;

      end if;

      -- Assert OUTPUT while the delay counter is running.
      if (delayCtr /= 0) then
        OUTPUT  <=  '1';
      else
        OUTPUT  <=  '0';
      end if;
    end if;
  end process pDelay;

end architecture behaviour;

Sie hatten keinen Reset-Eingang, aber das Design benötigt einen. Abgesehen davon und als allgemeine Richtlinien: Verwenden Sie keine Variablen, verwenden Sie Signale; Verwenden Sie Rising_edge nur mit einer Uhr; Verwenden Sie keine Zustandsmaschinen, es sei denn, Sie müssen es unbedingt tun (einige verwenden sie für alles, eine schlechte Angewohnheit).

Übrigens bestand das Problem in Ihrem Design darin, dass Sie zwei Prozesse hatten, die einen Ausgangsport ansteuerten.

Ich würde nicht sagen, dass es eine schlechte Angewohnheit ist, Maschinen zu benutzen, wo es möglich ist. Es wird Ihnen ein etwas größeres Design geben, aber Sie haben auch mehr Selbstvertrauen. Ich habe kürzlich ein Projekt gemacht, bei dem ich versucht habe, eine Sache ohne FSM zu machen, und es war schmerzhaft, weil ich in dieser Sache einen Fehler hatte und ungefähr einen Tag damit verbracht habe, ihn zu finden und es schließlich mit FSM zu machen. Aber trotzdem gute Arbeit :)
@Staszek, ich weiß, dass du es nicht tun würdest, aber ich tue es und als letztes Fazit, nicht mein erstes :-) Gute Anleitung für einen Neuling. Lass uns keine große Kommentardiskussion führen (alle), das wird zu lang, ich gehe gerne in den Chat, wenn du/jemand möchte.
  1. Nur für Signale verwenden rising_edge, die Uhren sein sollen.

  2. Sie können kein Signal zuweisen oder in zwei verschiedenen Prozessen ausgeben.

  3. Sie haben nicht genau angegeben, was Sie erreichen möchten, aber ich denke, dass Sie keinen Puffer für verwenden müssen (und sollten) OUTPUT.

Dieser Code sollte wie erwartet funktionieren (wenn ich Sie richtig verstehe):

library ieee;
use ieee.std_logic_1164.all;

entity trigger_slave is
    generic (
        OUT_ON_PERIOD   : integer := 10 - 1                                 
    );
    port (
        clk_1MHz        : in std_logic;
        resetn          : in std_logic;

        enable          : in std_logic;
        output          : out std_logic
    );
end trigger_slave;

architecture behavior of trigger_slave is

type state_t is (IDLE, COUNTING);
signal machine: state_t;

begin   

    process (clk_1MHz)  
        variable counter        : integer range 0 to OUT_ON_PERIOD := 0;
    begin
        if resetn = '0' then
            machine <= IDLE;
        elsif rising_edge(clk_1MHz) then

            case machine is

            when IDLE =>

                machine <= IDLE;

                if enable = '1' then
                    counter := 0;
                    machine <= COUNTING;
                end if;

            when COUNTING =>

                machine <= COUNTING;

                if (counter = OUT_ON_PERIOD) then
                    machine <= IDLE;
                else 
                    counter := counter + 1;
                end if; 

            when others =>

                machine <= IDLE;

            end case;

        end if;
    end process;

output <= '1' when machine = COUNTING else '0';

end behavior;
Sowohl im ersten Prozess als auch als letzte Anweisung weisen Sie „OUTPUT“ zu
Vielen Dank für das Beispiel. 1. Ich konnte die Zeile "output <= '1' when machine = COUNTING else '0';" nicht kompilieren. 2. Ich werde versuchen, dies mit diesem zusätzlichen "resetn" zu tun
Was ist die Fehlermeldung?