Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

Implementing a program counter

Hello!

Im implementing a CPU, so i need a PC (program counter). My instructions are at PC because we dont need to have a memory.

My problem is:

My BEQ instruction is delayed by one instruction

(BEQ is like something, if register1 = register2 then jump)

Example:

move r1,10 <- execute

move r2,10 <-execute

beq r1,r2,line5 <-execute

add r1,r2 <- execute and jump

move r3,r1

line5: sub r1,r2 <- continue...

i dont know why it is executing the next instruciton (add) then jumping.

Is it a delay problem?

thanks in advance.

I'm Using quartus web edition.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity PC is
 
 port(
   input : in std_logic_vector(7 downto 0);
   output : out std_logic_vector(7 downto 0);
   PCin :in std_logic;
   address : in std_logic_vector(3 downto 0);
   PCJR: in std_logic;
   PCJump: in std_logic;
   BEQ: in std_logic;
   BEQ_control : in std_logic;
 
   clock : in std_logic;
   indice : out std_logic_vector(7 downto 0)
 
  );
 
end PC;
 
 
architecture logic of PC is
type instructions is array(0 to 8) of std_logic_vector(7 downto 0);
signal ins : instructions;
--signal aux : std_logic_vector(7 downto 0);
--signal canJump : std_logic;
begin
 
--Instructions
 ins(0) <= "11000001";
 ins(1) <= "11001011";
 ins(2) <= "00100011";
 ins(3) <= "11000010";
 ins(4) <= "11011010";
 ins(5) <= "11011110";
 ins(6) <= "11011001";
 ins(7) <= "11000101";
 ins(8) <= "01100110";
 
 process(clock)
 variable ind : integer :=0;
 
 begin
 
  if(clock'event and clock = '1') then
 
   if(PCin = '1') then -- send instruction and increment
 
 
 
 
    output <= ins(ind);
    ind := ind + 1;
    --indice   <= CONV_STD_LOGIC_VECTOR(ind,8); 
 
 
 
   elsif(PCJR = '1') then -- JR
    ind     := CONV_INTEGER(UNSIGNED(input));
 
   elsif(PCJump = '1') then --JUmp
    ind     := CONV_INTEGER(UNSIGNED(address));
 
 
 
 
 
   elsif(beq = '1') then
 
    if(beq_control = '1') then
  -- PC - 8
       ind := ind - (CONV_INTEGER(UNSIGNED(address)));
 
    else
--PC + 8
     ind := ind  + (CONV_INTEGER(UNSIGNED(address)));
     --indice   <= CONV_STD_LOGIC_VECTOR(ind,8);
 
 
 
 
 
 
    end if;
 
 
 
 
 
   end if;
 
  --output <= aux;
  end if;
   ind := ind;
 end process;
 
 
 
end logic;

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Using variables is usually a bad coding style.

    I do not understand why many instructions are commented out. Please edit the code above to remove lines that are not meant to be there.

    You do not need the instruction ind := ind; in the end. It does not do anything.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Here it is.

    But my ind is the position of the array

    i mean like in C vet[i]

    If it isnt good, what can i do ?

    i don't think i can do this with std_logic, or bit. or i can?

    thanks

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
     
    entity PC is
     
     port(
       input : in std_logic_vector(7 downto 0);
       output : out std_logic_vector(7 downto 0);
       PCin :in std_logic;
       address : in std_logic_vector(3 downto 0);
       PCJR: in std_logic;
       PCJump: in std_logic;
       BEQ: in std_logic;
       BEQ_control : in std_logic;
     
       clock : in std_logic;
       indice : out std_logic_vector(7 downto 0)
     
      );
     
    end PC;
     
     
    architecture logic of PC is
    type instructions is array(0 to 8) of std_logic_vector(7 downto 0);
    signal ins : instructions;
     
    begin
     
    --Instructions
     ins(0) <= "11000001";
     ins(1) <= "11001011";
     ins(2) <= "00100011";
     ins(3) <= "11000010";
     ins(4) <= "11011010";
     ins(5) <= "11011110";
     ins(6) <= "11011001";
     ins(7) <= "11000101";
     ins(8) <= "01100110";
     
     process(clock)
     variable ind : integer :=0;
     
     begin
     
      if(clock'event and clock = '1') then
     
       if(PCin = '1') then -- send instruction and increment
     
     
     
     
        output <= ins(ind);
        ind := ind + 1;
        
     
     
     
       elsif(PCJR = '1') then -- JR
        ind     := CONV_INTEGER(UNSIGNED(input));
     
       elsif(PCJump = '1') then --JUmp
        ind     := CONV_INTEGER(UNSIGNED(address));
     
     
     
     
     
       elsif(beq = '1') then
     
        if(beq_control = '1') then
      -- PC - 8
           ind := ind - (CONV_INTEGER(UNSIGNED(address)));
     
        else
    --PC + 8
         ind := ind  + (CONV_INTEGER(UNSIGNED(address)));
         
     
     
     
     
     
        end if;
     
     
     
     
     
       end if;
     
     
      end if;
     
     end process;
     
     
     
    end logic;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I asked you to edit the first post, not to post a second one :)

    And now you removed so much code that I doubt that the code does anything at all.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I dont quite understand your problem. From your code the output only changes when PCin is high, and it outputs whatever the last instruction was.