Forum Discussion

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

program counter don't work

I write a program about simple cpu in quartuss II v 9.1 sp2 . Beginning I put all instructions to ram then fetch each instruction to Intruction register and decode it .Normally when fetch the program counter must increased by 1 but my program not ,it point the top address of ram forever I don't know to debug it I try many way to debug it but result of simulation remain the same

my code

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use ieee.std_logic_signed.all;

entity CU is

port( Reset : in std_logic;

Clock : in std_logic;

Enter : in std_logic; --enable CU

input : in std_logic_vector(7 downto 0));

end CU;

architecture behavior of CU is

type states is (start,fetch,decode,load,store,add,sub,inputa,jz,jpos,halt);

signal y:states;

type ram is array(31 downto 0) of std_logic_vector(7 downto 0);

signal reg:ram;

signal IR:std_logic_vector(7 downto 0);

signal A :std_logic_vector(7 downto 0);

shared variable pc :std_logic_vector(4 downto 0);

signal addr:std_logic_vector(4 downto 0);

begin

--transition state

t: process(Clock,Reset)

begin

if(Enter='1')then

if(Reset='0')then

y <=start;

elsif(Clock'event and Clock='1')then

case y is

when start => y <= fetch;

when fetch => y <= decode;

when decode => if (IR(7 downto 5)="000") then y <= load;

elsif(IR(7 downto 5)="001") then y <= store;

elsif(IR(7 downto 5)="010") then y <= add;

elsif(IR(7 downto 5)="011") then y <= sub;

elsif(IR(7 downto 5)="100") then y <= inputa;

elsif(IR(7 downto 5)="101") then y <= jz;

elsif(IR(7 downto 5)="110") then y <= jpos;

elsif(IR(7 downto 5)="111") then y <= halt;

else y <= decode;

end if;

when load => y <= start;

when store => y <= start;

when add => y <= start;

when sub => y <= start;

when inputa =>if(ENTER='0')then y <= inputa;

else y <= start;

end if;

when jz => y <= start;

when jpos => y <= start;

when halt => y <= halt;

when others => y <= start;

end case;

end if;

end if;

end process t;

O: process(y)

begin

--three bits on left is command the others is address

reg(0) <="10000000";

reg(1) <="00111110";

reg(2) <="10000000";

reg(3) <="00111111";

reg(4) <="00011110";

reg(5) <="01111111";

reg(6) <="10110000";

reg(7) <="11001100";

reg(8) <="00011111";

reg(9) <="01111110";

reg(10)<="00111111";

reg(11)<="11000100";

reg(12)<="00011110";

reg(13)<="01111111";

reg(14)<="00111110";

reg(15)<="11000100";

reg(16)<="00011110";

reg(17)<="11111111";

case y is

when fetch => IR<=reg(to_integer(unsigned(pc)));

pc:=pc+1; --problem pc is not increased by 1

when load => addr<=IR(4 downto 0);

A <=reg(to_integer(unsigned(addr)));

when store => addr<=IR(4 downto 0);

reg(to_integer(unsigned(addr)))<=A;

when add => addr<=IR(4 downto 0);

A<=A+reg(to_integer(unsigned(addr)));

when sub => addr<=IR(4 downto 0);

A<=A-reg(to_integer(unsigned(addr)));

when inputa => A<=input;

when jz => if(A="00000000")then

pc:=IR(4 downto 0);

end if;

when jpos => if(A>"00000000")then

pc:=IR(4 downto 0);

end if;

when others => IR<=reg(0);

end case;

end process o;

end behavior;

if somewhere of the code is wrong or not very well and information that I tell to you is not clear please give some advice because I don't quite have experience in vhdl and english language.Thank you for every answers.

5 Replies

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

    A few things first:

    --- Quote Start ---

    use ieee.numeric_std.all;

    use ieee.std_logic_signed.all;

    --- Quote End ---

    You shouldn't use those two libraries in the same code, it can lead to strange problems. Besides I guess that you'll do an ALU one day so you'll need both signed and unsigned operations, so I recommend to drop the non standard std_logic_signed library and use std_logic_signed with the signed and unsigned types.

    --- Quote Start ---

    shared variable pc :std_logic_vector(4 downto 0);

    --- Quote End ---

    Shared variables usually can't be synthesized and should only be used for debugging or test benches. You should rather use a signal, or a variable inside your second process. Besides I'm not sure the Quartus simulator supports shared variables.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I already change the type of pc to signal and put in second process ,the same result occur again .When I don't write use ieee.numeric_std.all; or use ieee.std_logic_signed.all; errors occur (object to_integer is used but not declared) , (can't determine definition of operator ""+"" ) respectively

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

    Lets get started.

    You need to use one of numeric_std or std_logic_arith. numeric_std library has the to_integer function in it, so you need to include it.

    Secondly - there are loads of problems with this code. This code is riddled with latches and code that is going to have differences in simulation and real hardware.:

    1. The "enter" signal - in the first process you have it as an asynchronous enable, but you havent included it in the sensitivity list. Sensitivity lists are ignored for synthesis and this process is going to cause you problems.

    2. Every time Y changes you are setting the values of reg to constants - why?

    3. PC is being incremented only when Y changes to fetch. But because it is in an asynchronous process, on real hardware it would be trying to increment a infinite number of times - whenever Y = fetch it keeps adding 1 until it moves out of fetch. In simulation it should only add once, but on real hardware it will not work because it will be trying to add one an infinite number of times.

    4. Looking at this code, it looks like you're a software programmer. Before you write VHDl you should try drawing your circruit diagram out in registers and gates. And then describe it in VHDL. VHDL is not a programming language.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    About point 3, Quartus *may* recognise the code as a state machine and in this case implement a hardware that will correspond to simulation and will increase the PC once each time Y is changed to fetch. But this would need to be verified with a synthesis... I'm not sure it will be recognised though because this code doesn't fit with Altera's recommended way of describing a state machine. Have a look here for the recommended code styles: http://www.altera.com/literature/hb/qts/qts_qii51007.pdf

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

    it wont, because you would usually have an enable here that enables a clocked process for the counter. In this code, the PC is incremented whenever Y is fetch, and then it latches it when Y changes.