Page 1 of 1

Errore "Multiple drivers due to the non-tri-state driver"

PostPosted: 27 Aug 2012, 23:40
by flz47655
Ciao a tutti

Sto scrivendo una semplice CPU "from scratch", ho però il seguente errore da Quartus II che non riesco a capire..

Error (13076): The node "CPU3BIT:inst|addr[1]" has multiple drivers due to the non-tri-state driver "CPU3BIT:inst|data[7]"
Error (13076): The node "CPU3BIT:inst|data[6]" has multiple drivers due to the non-tri-state driver "CPU3BIT:inst|data[6]"
..errori per tutti gli elementi di CPU3BIT:inst|data

Sembrerebbe un problema dovuto al fatto che il segnale data è sia un ingresso sia un'uscita ed istruzioni consecutive come

Code: Select all
addr    <= data(5 downto 0);
data    <= reg;


diano dei problemi, commentando l'istruzione data <= reg; il tutto compila senza problemi.

Il codice problematico è nell'implementazione dell'istruzione STORE che scrive nella memoria il contenuto del registro REG. Per fare ciò carica l'indirizzo contenuto nell'istruzione (quindi nel segnale DATA) sulla linea ADDR collegata alla memoria e copia il contenuto del registro REG sul segnale DATA collegato anch'esso alla memoria.

Come posso risolvere questo problema?

Ecco il codice:

Code: Select all
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity CPU3BIT is
   port (
      data:   inout   std_logic_vector(7 downto 0);   -- Memory Data
      addr:   out std_logic_vector(5 downto 0);   -- Memory Address
      we:   out std_logic;                        -- Memory Write Enable
      d_reg: out std_logic_vector(7 downto 0);   -- Register for Debug
      rst:   in   std_logic;
      clk:   in   std_logic);
end;

architecture CPU_ARCH of CPU3BIT is
   signal   reg:      std_logic_vector(7 downto 0);      -- Register   
   signal    pc:      std_logic_vector(5 downto 0);      -- Program Counter
begin
   d_reg <= reg;
   process(clk, rst)
   begin
      if (rst = '0') then          
         reg   <= (others => '0');   -- Initialize register
         pc      <= (others => '0');   -- start execution at memory location 0
         addr   <=   (others => '0');   -- read memory at location 0
      elsif rising_edge(clk) then
         -- Increment clock
         pc   <= pc + 1;             
         
         -- Read data
         case data(7 downto 6) is
            -- Load
            when "00" =>
               we    <= '0';
               addr    <= data(5 downto 0);               
               reg    <= data; -- TODO: data is not readed data
            -- Store
            when "01" =>
               we    <= '1';               
               addr    <= data(5 downto 0);
               data    <= reg; -- Error (13076): The node "CPU3BIT:inst|addr[1]" has multiple drivers due to the non-tri-state driver "CPU3BIT:inst|data[7]"

            -- Add
            when "10" =>
               reg <= std_logic_vector(unsigned(reg) + unsigned(data));
            when others => null;
         end case;
         
      end if;
   end process;
   
end CPU_ARCH;


E l'implementazione della memoria sincrona che ho fatto

Code: Select all
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity MSRAM is
   port (
      clk   : in std_logic;
      data   : inout std_logic_vector(7 downto 0):= "ZZZZZZZZ";
      addr  : in std_logic_vector (5 downto 0) := "ZZZZZZ";     
      we    : in std_logic := 'Z';       -- write enable      
      rst   : in std_logic
   );
end;

architecture SRAM_ARCH of MSRAM is   
   -- memory is 4x8 bit
   -- memory block are ( _ TO _ ) to keep first block first in init
   -- memory bit are ( _ DOWNTO _ ) to keep LSB at right
   type memory is array (0 to 3) of std_logic_vector (7 downto 0);
   signal ram_block : memory;
   shared variable address : integer;
begin

   process(clk, rst)
   begin      
      -- todo: remove reset to syntetize to lpm_ram
      if (rst = '0') then         
         data    <= (others => 'Z');         
         -- pre-written bytes into memory
         ram_block <= (
         "00000011",      -- Load Addr 3
         "10000101",    -- Add 5
         "01000011",    -- Store Addr 3
         "10101010");   -- Addr 3 = 170
      elsif rising_edge(clk) then      
         -- decode address
         address := to_integer(unsigned(addr));
            
         --   Write
         if(we = '1') then
            ram_block(address) <= data(7 downto 0);   -- write data into ram_block
            data <= "ZZZZZZZZ";                        -- data is High Z
         elsif(we = '0') then
            -- Read            
            data <= ram_block(address);            
         else
            -- we High Z
            data <= "ZZZZZZZZ";
         end if;
      
      end if;
   end process;   
end SRAM_ARCH;

Re: Semplice CPU

PostPosted: 28 Aug 2012, 09:12
by flz47655
Mi sa che voglio fare troppe cose in un colpo di clock :D ...
E' possibile realizzare una CPU senza pipeline che esegue istruzioni in un solo colpo di clock?

Re: Semplice CPU

PostPosted: 28 Aug 2012, 13:32
by deluca
se non hai risolto, appena ho tempo gli dò un'occhiatina al codice.

in un solo colpo di clock, cosa intendi, eseguire + istruzioni?

le risc eseguono 1 istruzione x ciclo di clock (di norma) senza pipeline.
Non mi è capitato mai di istanziare alu capaci di eseguire + di una istruzione per clk senza pipeline.

come mai questa richiesta?

Re: Semplice CPU

PostPosted: 28 Aug 2012, 13:51
by flz47655
Ciao,
Purtroppo non ho ancora risolto.

Con eseguire più istruzioni intendevo eseguire più "operazioni" al fine di eseguire una intera istruzione (in questo caso l'istruzione STORE) in un solo colpo di clock.

Non voglio eseguire più istruzioni ma solamente un istruzione completa (formata da più operazioni) in un solo colpo di clock.

In questo caso per eseguire l'istruzione STORE che è del tipo 01AAAAAA dove 01 è il numero dell'istruzione e la seconda parte è l'indirizzo di memoria su cui copiare il registro unico del processore devo:

1) Settare WE su 1 per abilitare la scrittura della memoria
2) Copiare parte di DATA (ovvero AAAAAA) su ADDR per dire alla memoria dove voglio scrivere
3) Copiare REG in DATA per dare alla memoria i dati che devo copiare

Sembra però che ci siano problemi nell'eseguire in contemporanea le istruzioni 2 e 3 perché dovrei "leggere e scrivere" DATA in contemporanea..

Note: Il codice non è finito (e pieno di altre cose da sistemare) ma prima di andare avanti volevo capire come risolvere una situazione del genere

EDIT: Ho sistemato il codice postato della RAM

Re: Semplice CPU

PostPosted: 29 Aug 2012, 22:13
by flz47655
Ormai ho abbandonato questa versione e sto provando a fare le cose per benino: macchina a stati in una cpu multiciclo
Era interessante comunque, a parte il codice specifico, capire l'errore

Ciao