So verbinden Sie UART mit BRAM in Xilinx Virtex 5

Ich versuche, eine einfache Schleife des Kommunikationssystems zwischen PC und FPGA Virtex 5 zu entwerfen, zu diesem Zweck habe ich ein BRAM mit einem UART-Modul verbunden, ich verwende VHDL als Hardwarebeschreibungssprache, der verwendete Speicher ist ein einfacher 16-Byte-Dual-Port-BRAM RAM mit einer Breite von 8 Bit; 16 Bytes Daten von einer Terminalsoftware lesen und dann zurückschicken soll, ist das Problem, dass ich die erste Adresse nicht schreiben kann (addra = 0) und das Schreiben ab der zweiten Adresse beginnt, also kann ich nur 15 Bytes schreiben in einem durchlauf, hier ist der code des fsm, der verwendet wird, um das system zu implementieren

proc_next_state: process(clk, reset, state)
begin
  if reset = '1' then
    state <= idle;
  elsif (rising_edge(clk)) then
    case state is
      when idle =>
        wea(0) <= rx_dv ;
        dina <= rx_byte; -- input of BRAM's port A.
        ENB <= '0'; -- Enable signal for port B
        tx_DV <= '0'; -- data valid signal for uart transmitting interface.
        tx_byte <=(others => '0'); -- byte to be loaded to uart transmitting interface
        if rx_dv = '1' then -- data valid signal for uart receiving interface
          state <= writing; -- if rx_dv is asserted move to the writing state
        else
          state <= idle;                              -- keep idle
        end if;

      when writing => 
        if addra = "1111" then -- if the whole block is written move to the reading state
          state <= reading;
        else
          state<= idle;
        end if;
        wea <= (others => '1');
        dina <= rx_byte;
        ENB <= '0';
        tx_DV <= '0';
        addra <= addra + 1;
        tx_byte <= (others => '0');

      when reading =>
        wea <= (others => '0');
        dina <= (others => '0');
        ENB <= '1';
        tx_DV <= '1';
        tx_byte <= doutb;
        if addrb = "1111" then -- if the 16 bytes data are fully read move to state done
          state <= done;
        else
          state <= waiting; 
        end if;
        addrb <= addrb + 1;

      when waiting =>
        wea <= (others => '0');
        dina <= (others => '0');
        ENB <= '0';
        tx_DV <= '0';
        tx_byte <= (others => '0');
        if tx_done = '1' then
          state <= reading; -- read a new byte when tx_done is asserted high
        else
          state <= waiting; -- keep waiting
        end if;

      when others => -- remain in this state for one clock period then move to idle
        wea(0) <= '0';
        dina <= (others => '0');
        ENB <= '0';
        tx_DV <= '0';
        tx_byte <= (others => '0');
        addra <= "0000";
        addrb <= "0000";
        state <= idle; 
    end case;
  end if;
end process;

Dieser Teil des Codes ist für die Signale, die ich für Simulationszwecke verwendet habe

Din <= dina;
Wra <= wea(0);
Rdb <= enb;
i_rx_DV <= rx_DV;
o_tx_done <= tx_done ;
dout <= doutb;
o_rx_byte <= rx_byte;
w_SM_Main <= "000" when state = Idle else
             "001" when state = writing else
             "010" when state = reading else
             "011" when state = waiting else
             "100" when state = done else
             "101"; -- you should not reach this value

Das folgende Bild zeigt die Simulationsergebnisse des Schreibens von dina in addra = 0

Geben Sie hier die Bildbeschreibung ein

Und dieses Bild zeigt die Simulationsergebnisse des Lesens von doutb von addrb = 0

Geben Sie hier die Bildbeschreibung ein

Können Sie mir bitte sagen, warum ich den Wert 0 auf addressb = 0 lese, obwohl der erste empfangene Wert von 0 abweicht?

Bitte stellen Sie eine spezifische Frage electronic.stackexchange.com/help/how-to-ask
Wenn die Sim Ihnen sagt, dass 0 an der Adresse 0 ist, dann glauben Sie ihr. Sehen Sie sich die Zustände in der Simulation an und sehen Sie, ob sie sich so verhält, wie Sie es beabsichtigt haben. (Ich bin kein großer Fan von Einzelprozess-Zustandsmaschinen.)
Setzen Sie den Status nicht in Ihre Prozesssensitivitätsliste. Für getaktete Logik sollte es Clock und Reset sein (bei asynchronem Reset).

Antworten (1)

Basierend auf Ihrer zweiten Bildschirmaufnahme lesen Sie bei addressb=1 NOT addressb=0.

RdB wird im "Lese"-Zustand hoch gesetzt und addressb wird inkrementiert, aber diese Werte werden erst im folgenden Taktzyklus aus dem Register ausgelesen. Wenn daher der aktualisierte (hohe) RdB vom BRAM gesehen wird, wurde der Ausgang des addressb-Registers bereits auf 1 inkrementiert.