I have this PC
module, very simple (Code at the end). I first generate some input signal port_int
and at the end of the process say pc_out <= port_int
. My goal is to either increment or add or subtract from PC, depending on input signals.
In the simulation, the internal port_int
signal works fine, but pc_out
doesn't. Why is this happening? Look at the simulation:
Look how port_int
changes as it should, while pc_out
is late. Later in the simulation, pc_out
gets even worse, changing irregularly, not even just being late.
What am I doing wrong? Is there another way to change pc_out
? Bcoz you can't change out
signals, and I've been told that inout
is extremely bad practice..
Here's the code:
entity PC is
Port ( clk : in STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
pc_out : out STD_LOGIC_VECTOR (3 downto 0);
data : in STD_LOGIC_VECTOR (3 downto 0); -- jump value
zero : in STD_LOGIC; -- jump condition
jmp_en : in STD_LOGIC; -- jump enable
jmp_dir : in STD_LOGIC; -- jump direction
ctrl_en : out STD_LOGIC); -- output signal
end PC;
architecture Behavioral of PC is
type state_type is (s0, s1, s2, s3);
signal reg_state, next_state : state_type;
signal port_int : std_logic_vector(3 downto 0);
begin
state_transition: process(clk, reset)
begin
if (reset = '1') then
reg_state <= s0;
elsif(rising_edge(clk)) then
reg_state <= next_state;
end if;
end process;
next_state_logic: process(reg_state, enable)
begin
case reg_state is
when s0 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s1 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s2 =>
next_state <= s3;
when s3 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
end case;
end process;
output_logic: process(reg_state, zero, jmp_en, jmp_dir, data)
begin
case reg_state is
when s0 =>
pc_out <= "0000";
port_int <= "0000";
ctrl_en <= '0';
when s1 =>
ctrl_en <= '0';
when s2 =>
if(zero = '1' and jmp_en = '1' and jmp_dir = '1')then
port_int <= port_int + data; -- jump forward
elsif(zero = '1' and jmp_en = '1' and jmp_dir = '0')then
port_int <= port_int - data; -- jump backward
else -- nije ispunjen uslov skoka
port_int <= port_int + '1'; -- increment PC
end if;
pc_out <= port_int;
when s3 =>
ctrl_en <= '1';
end case;
end process;
end Behavioral;
EDIT:
When I import the module in a whole processor, this happens:
the same pc_out
signal acts strangely, adn all the inputs are the same. I use the pc_out
signal just in one place, to select memory.
Why isn't it behaving normally? What could have caused this?
The second process (output_logic: process), which computes the output values, has some problems.
First, recall that it implements a combinational circuit (therefore, memoryless), so equations like port_int <= port_int + data can only be computed if the value of port_int is stored somewhere. By the way, after fixing the code, you can drop the internal signal port_int and use pc_out directly.
Second, being this process a combinational circuit, its full truth table must be specified; otherwise, latches will be inferred. Note, for example, that only the value of ctrl_en is specified in state s1. You must either specify all output values (same list) in all states or, equivalently, you can make a list of output values before the case statements, so the compiler will use them as default values when the values are not explicitly declared.