vhdl: object subtype is not locally static - vhdl

using GHDL to compile some VHDL getting a weird error. simulation compiler for VHDL fails on line: "case i_cli_adr is" with error message: "vhdl: object subtype is not locally static". How to fix it?
library ieee;
use ieee.std_logic_1164.all;
entity sim_regs is
generic(
LW : integer := 16
);
port(
i_sys_clk : in std_logic;
i_sys_rst_n : in std_logic;
i_cli_vld : in std_logic;
i_cli_wnr : in std_logic;
i_cli_adr : in std_logic_vector(LW-1 downto 0);
i_cli_dat : in std_logic_vector(LW-1 downto 0);
);
end entity;
architecture sim of sim_regs is
signal testreg0 : std_logic_vector(LW-1 downto 0);
signal testreg1 : std_logic_vector(LW-1 downto 0);
signal awrite : std_logic;
begin
awrite <= i_cli_vld and i_cli_wnr;
process(i_sys_clk)
begin
if (i_sys_clk = '1' and i_sys_clk'event) then
if (i_sys_rst_n = '0') then
testreg0 <= (others => '0');
testreg1 <= (others => '0');
end if;
else
o_cli_rvld <= '0';
if (awrite = '1') then
case i_cli_adr is
when 0 => testreg0 <= i_cli_dat;
when 1 => testreg1 <= i_cli_dat;
end case;
end if;
end if;
end process;
end architecture;

The fix was to hard code the size of address internally
architecture sim of sim_regs is
signal aaddr : std_logic_vector(15 downto 0);
begin
aaddr <= i_cli_adr and X"FFFF";
--- now can use aaddr in place of i_cli_adr in "case"
Complete Example:
library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
entity sim_regs is
generic(
LW : integer := 16
);
port(
i_sys_clk : in std_logic;
i_sys_rst_n : in std_logic;
i_cli_vld : in std_logic;
i_cli_wnr : in std_logic;
i_cli_adr : in std_logic_vector(LW-1 downto 0);
i_cli_dat : in std_logic_vector(LW-1 downto 0);
o_cli_rdat : out std_logic_vector(LW-1 downto 0);
o_cli_rvld : out std_logic;
i_cli_rbsy : in std_logic
);
end entity;
architecture sim of sim_regs is
signal testreg0 : std_logic_vector(LW-1 downto 0);
signal testreg1 : std_logic_vector(LW-1 downto 0);
signal testreg2 : std_logic_vector(LW-1 downto 0);
signal testreg3 : std_logic_vector(LW-1 downto 0);
signal aaddr : std_logic_vector(15 downto 0);
signal awrite : std_logic;
signal aread : std_logic;
begin
awrite <= i_cli_vld and i_cli_wnr;
aread <= i_cli_vld and not i_cli_wnr and not i_cli_rbsy;
aaddr <= i_cli_adr and X"FFFF";
process(i_sys_clk)
begin
if (i_sys_clk = '1' and i_sys_clk'event) then
if (i_sys_rst_n = '0') then
o_cli_rvld <= '0';
o_cli_rdat <= (others => '0');
testreg0 <= (others => '0');
testreg1 <= (others => '0');
testreg2 <= (others => '0');
testreg3 <= (others => '0');
end if;
else
o_cli_rvld <= '0';
if (awrite = '1') then
case aaddr is
when X"0000" => testreg0 <= i_cli_dat;
when X"0001" => testreg1 <= i_cli_dat;
when X"0002" => testreg2 <= i_cli_dat;
when X"0003" => testreg3 <= i_cli_dat;
when others => null;
end case;
elsif (aread = '1') then
o_cli_rvld <= '1';
case aaddr is
when X"0000" => o_cli_rdat <= testreg0;
when X"0001" => o_cli_rdat <= testreg1;
when X"0002" => o_cli_rdat <= testreg2;
when X"0003" => o_cli_rdat <= testreg3;
when others => o_cli_rdat <= (others => '0');
end case;
end if;
end if;
end process;
end architecture;

Related

Unable to output data entered into a register

I have a simple program. I am trying to input the counter output into a memory address register and output the data that is in the memory address register.
Memory Address Register Code:
library ieee;
use ieee.std_logic_1164.all;
entity mar is
port(
mar_clk, mar_clr, mar_en : in std_logic;
mar_datain : in std_logic_vector(3 downto 0);
mar_dataout : out std_logic_vector(3 downto 0)
);
end entity;
architecture behavioral of mar is
begin
process(mar_clk, mar_clr, mar_en, mar_datain)
begin
if(mar_clr = '1') then
mar_dataout <= (others => '0');
elsif(mar_clk'event and mar_clk = '1') then
if(mar_en = '0') then
mar_dataout <= mar_datain;
end if;
end if;
end process;
end behavioral;
Buffer4 Code:
library ieee;
use ieee.std_logic_1164.all;
entity buffer4 is
port(
buff4_en : in std_logic;
datain : in std_logic_vector( 3 downto 0 );
dataout : out std_logic_vector( 3 downto 0 )
);
end entity;
architecture behavioral of buffer4 is
begin
process(buff4_en, datain)
begin
if(buff4_en = '1') then
dataout <= datain;
else
dataout <= (others => 'Z');
end if;
end process;
end behavioral;
Program Counter Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity pc is
port(
pc_ld, pc_en, pc_clk, pc_rst : in std_logic;
pc_datain : in std_logic_vector(3 downto 0);
pc_dataout : out std_logic_vector(3 downto 0)
);
end entity;
architecture behave of pc is
signal count : std_logic_vector(3 downto 0) := "0001";
signal temp : integer;
begin
process(pc_clk, pc_rst)
begin
if(pc_rst = '1') then
count <= (others => '0');
elsif(pc_clk'event and pc_clk = '1') then
if(pc_ld = '1') then
count <= pc_datain;
elsif(pc_en = '1') then
count <= count;
temp <= conv_integer(count);
if(temp = 16) then
count <= (others => '0');
end if;
count <= count + 1;
end if;
end if;
end process;
pc_dataout <= count;
end behave;
Test Program Code:
library ieee;
use ieee.std_logic_1164.all;
entity test is
end entity;
architecture behave of test is
component mar
port(
mar_clk, mar_clr, mar_en : in std_logic;
mar_datain : in std_logic_vector( 3 downto 0 );
mar_dataout : out std_logic_vector( 3 downto 0 )
);
end component;
component pc
port(
pc_ld, pc_en, pc_clk, pc_rst : in std_logic;
pc_datain : in std_logic_vector(3 downto 0);
pc_dataout : out std_logic_vector(3 downto 0)
);
end component;
component buffer4
port(
buff4_en : in std_logic;
datain : in std_logic_vector( 3 downto 0 );
dataout : out std_logic_vector( 3 downto 0 )
);
end component;
signal databus : std_logic_vector(7 downto 0);
signal addressbus : std_logic_vector(3 downto 0);
signal gclk : std_logic;
signal mar_clr, mar_en : std_logic;
signal pc_ld, pc_en, pc_rst : std_logic;
signal buff4_en : std_logic;
signal dataout : std_logic_vector(3 downto 0);
signal mar_datain, mar_dataout : std_logic_vector(3 downto 0);
signal pc_dataout : std_logic_vector(3 downto 0);
begin
U1 : pc port map(pc_ld, pc_en, gclk, pc_rst, databus(3 downto 0), pc_dataout);
U2 : buffer4 port map(buff4_en, pc_dataout, databus(3 downto 0));
U3 : mar port map(gclk, mar_clr, mar_en, databus(3 downto 0), addressbus);
stim_process : process
begin
gclk <= '0';
wait for 10 ns;
pc_ld <= '0';
pc_en <= '1';
pc_rst <= '0';
buff4_en <= '1';
mar_clr <= '0';
mar_en <= '0';
gclk <= '1';
wait for 10 ns;
gclk <= '0';
wait for 10 ns;
assert false report "Reached end of test. Start GTKWave";
wait;
end process;
end behave;
This is the output when I run the program
As seen the Memory Address Registers takes the input and doesn't output it on the address bus. How can I make the Memory Address Register output the data on the address bus?
This is the logic for writing to your memory address output register inside your 'MAR' component:
if(mar_clr = '1') then
mar_dataout <= (others => '0');
elsif(mar_clk'event and mar_clk = '1') then
if(mar_en = '0') then
mar_dataout <= mar_datain;
end if;
end if;
If appears that at your rising edge of clock (mar_clk'event and mar_clk = '1') in the waveforms that mar_clr and mar_en are both undefined U's. They have not got their values yet when the rising edge occurs.
You need to redo your testbench to make sure input signals are stable+defined before the rising edge so they are sampled correctly. Then mar_dataout <= mar_datain; should take correctly.
Could try moving initial wait statement like so:
gclk <= '0';
pc_ld <= '0';
pc_en <= '1';
pc_rst <= '0';
buff4_en <= '1';
mar_clr <= '0';
mar_en <= '0';
wait for 10 ns;
gclk <= '1';
wait for 10 ns;

VHDL Microprocessor 16 bits

I'm trying to make a microprocessor architecture and I'm stuck. My accumulator, IR and PC don't seem to be working and I can't figure out why.
their outputs stay always undefined. I check the mapping and the other components of the mp they're are all correct the problem is somewhere in these registers.
------------------------------------------------------
-- ALU
------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.up_pack.all;
entity alu is
port ( A, B : in std_logic_vector(15 downto 0);
alufs : in ALU_FCTS;
S : out std_logic_vector( 15 downto 0));
end alu;
architecture arch_alu of alu is
begin
S <= "0000000000000000"; -- sortie par défaut
process(A, B, alufs)
begin
case alufs is
when ALU_B => S <= B;
when ALU_SUB => S <= std_logic_vector(unsigned(B) - unsigned(A));
when ALU_ADD => S <= std_logic_vector(unsigned(B) + unsigned(A));
when ALU_B_INC => S <= std_logic_vector(unsigned(B) + 1);
when ALU_AND => S <= A and B;
when ALU_OR => S <= A or B;
when ALU_XOR => S <= A xor B;
when others => S <= "0000000000000000";
end case;
end process;
end arch_alu;
------------------------------------------------------
-- ACCUMULATER
------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity accumulator is
port( clk, raz, load : in std_logic;
data_in : in std_logic_vector(15 downto 0);
data_out : out std_logic_vector(15 downto 0);
acc15, accz : out std_logic );
end accumulator;
architecture arch_acc of accumulator is
signal q_reg : std_logic_vector(15 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
if raz='1' then q_reg <= (others => '0');
elsif load='1' then q_reg <= std_logic_vector(unsigned(q_reg) + unsigned(data_in)); end if;
end if;
end process;
data_out <= q_reg;
acc15 <= q_reg(15);
accz <= '1' when q_reg = "0000000000000000";
end arch_acc;
------------------------------------------------------
-- REGISTER PC
------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity pc_reg is
port( clk, raz, load : in std_logic;
data_in : in std_logic_vector(11 downto 0);
data_out : out std_logic_vector(11 downto 0) );
end pc_reg;
architecture arch_pc_reg of pc_reg is
signal interne : std_logic_vector(11 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
if raz='1' then interne <= (others => '0');
elsif load='1' then interne <= data_in;
end if;
end if;
end process;
data_out <= interne;
end arch_pc_reg;
------------------------------------------------------
-- IR (Instruction Register)
------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.up_pack.all;
entity ir_reg is
port( clk, raz, load : in std_logic;
data_in : in std_logic_vector(15 downto 0);
data_out : out std_logic_vector(11 downto 0);
opcode : out OPCODE);
end ir_reg;
architecture arch_ir_reg of ir_reg is
signal interne : std_logic_vector(3 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
if raz='1' then data_out <= (others => '0');
elsif load='1'
then
data_out <= data_in(11 downto 0);
interne <= data_in(15 downto 12);
end if;
end if;
end process;
opcode <= OP_LDA when interne="0000" else
OP_STO when interne="0001" else
OP_ADD when interne="0010" else
OP_SUB when interne="0011" else
OP_JMP when interne="0100" else
OP_JGE when interne="0101" else
OP_JNE when interne="0110" else
OP_STP when interne="0111" else
OP_AND when interne="1000" else
OP_OR when interne="1001" else
OP_XOR when interne="1010" else
OP_LDR when interne="1011" else
OP_LDI when interne="1100" else
OP_STI when interne="1101" else
OP_JSR when interne="1110" else
OP_RET when interne="1111" else
OP_UNKNOWN;
end arch_ir_reg;
This is not an answer, but a testbench for you to work with. Your accumulator seems to work fine. I tested it with the testbench below. Use it as resource for writing testbenches for the rest of your modules. (You can write a test bench to test all the modules together or individually, just FYI)
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_accumulator is
end tb_accumulator;
architecture behav of tb_accumulator is
signal clk : std_logic := '0';
signal raz : std_logic := '1';
signal load : std_logic := '0';
signal data_in : std_logic_vector(15 downto 0) := (others => '0');
signal data_out : std_logic_vector(15 downto 0) := (others => '0');
signal acc15 : std_logic := '0';
signal accz : std_logic := '0';
begin
--Assign values for signals being passed into accumulator.
clk <= not clk after 2.5 ns;
data_in <= "0000000000000001";
raz <= '0' after 90 ns; --You can do this instead of forcing a signal. Set at what times you want it to change values.
load <= '1' after 100 ns;
accu_inst : entity work.accumulator
port map(
clk => clk,
raz => raz,
load => load,
data_in => data_in,
data_out => data_out,
acc15 => acc15,
accz=> accz
);
end behav;

How do you displayed on HDMI screen with FPGA board?

I'm working on a project.
The goal of this project is to connect a USB-keyboard and a HDMI-display with each other using a FPGA board. That means we want to show each letter and character of the keyboard on the display when we press the key.
For the project I have chosen an Altys board build by Digilent based on FPGA Xilinx Spartan6.
For the moment I have connected the keyboard with the FPGA board and can receive data from the keyboard. It means that when I press the letter LEDs of the board light up.
I have also implemented a led sequence for each letter.
Now I try to send the letter from the keyboard to the display with HDMI output port but I have some trouble.
Does anyone have any ideas or any codes to display something with the HDMI port of FPGA board ?
Thanks for your help
The code for the keyboard connection
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity main is
port(
k_clk: in std_logic;
k_d: inout std_logic;
Led: out std_logic_vector(7 downto 0);
clk: in std_logic;
char: out std_logic_vector(7 downto 0)
);
end main;
architecture Behavioral of main is
signal s_k_clk: std_logic :='0';
signal ch: std_logic_vector(7 downto 0) :=(others=>'0');
signal k_clk1: std_logic;
--signal pulseInternal : std_logic;
signal makeCodeTemp : std_logic_vector(7 downto 0);
signal makeCode : std_logic_vector(7 downto 0);
signal data : std_logic_vector(21 downto 0);
signal charTemp :std_logic_vector(7 downto 0);
--signal char :std_logic_vector(7 downto 0);
begin
--------------------------------------------------------------
makeCodeTemp <= data(9 downto 2); -- Scan code window
makeCode(7) <= makeCodeTemp(0);
makeCode(6) <= makeCodeTemp(1);
makeCode(5) <= makeCodeTemp(2);
makeCode(4) <= makeCodeTemp(3);
makeCode(3) <= makeCodeTemp(4);
makeCode(2) <= makeCodeTemp(5);
makeCode(1) <= makeCodeTemp(6);
makeCode(0) <= makeCodeTemp(7);
--------------------------------------------------------------
Led(7 downto 0) <= ch(7 downto 0);
k_clk1<=k_clk xor s_k_clk;
p0:process(clk)
begin
if rising_edge(clk)then
s_k_clk<=k_clk;
end if;
end process;
p1:process(clk)
begin
if rising_edge(clk)then
if (k_clk1='1') then
data(21 downto 1) <= data(20 downto 0);
data(0) <= k_d;
--ch<=ch+1;
end if;
end if;
end process;
p2:process(clk)
begin
if rising_edge(clk) then
if data(20 downto 13) = x"0F" then char <= charTemp;
end if;
end if;
end process;
p3:process(clk)
begin
if rising_edge(clk) then
if charTemp=x"41" then
ch(0)<='1';
elsif charTemp=x"42" then
ch(1)<='1';
elsif charTemp=x"43" then
ch(2)<='1';
elsif charTemp=x"44" then
ch(3)<='1';
elsif charTemp=x"45" then
ch(4)<='1';
end if;
end if;
end process;
charTemp <= x"41" when makeCode = x"1C" else --A
x"42" when makeCode = x"32" else --B
x"43" when makeCode = x"21" else --C
x"44" when makeCode = x"23" else --D
x"45" when makeCode = x"24" else --E
x"46" when makeCode = x"2B" else --F
x"47" when makeCode = x"34" else --G
x"48" when makeCode = x"33" else --H
x"49" when makeCode = x"43" else --I
x"4A" when makeCode = x"3B" else --J
x"4B" when makeCode = x"42" else --K
x"4C" when makeCode = x"4B" else --L
x"4D" when makeCode = x"3A" else --M
x"4E" when makeCode = x"31" else --N
x"4F" when makeCode = x"44" else --O
x"50" when makeCode = x"4D" else --P
x"51" when makeCode = x"15" else --Q
x"52" when makeCode = x"2D" else --R
x"53" when makeCode = x"1B" else --S
x"54" when makeCode = x"2C" else --T
x"55" when makeCode = x"3C" else --U
x"56" when makeCode = x"2A" else --V
x"57" when makeCode = x"1D" else --W
x"58" when makeCode = x"22" else --X
x"59" when makeCode = x"35" else --Y
x"5A" when makeCode = x"1A" else --Z
x"30" when makeCode = x"45" else --0
x"31" when makeCode = x"16" else --1
x"32" when makeCode = x"1E" else --2
x"33" when makeCode = x"26" else --3
x"34" when makeCode = x"25" else --4
x"35" when makeCode = x"2E" else --5
x"36" when makeCode = x"36" else --6
x"37" when makeCode = x"3D" else --7
x"38" when makeCode = x"3E" else --8
x"39" when makeCode = x"46" else --9
x"2F" when makeCode = x"5A" else --ENTER
x"5C" when makeCode = x"66" else --Backspace
x"00"; --Null
end Behavioral;
**The code for HDMI display: **
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity dvid is
Port ( clk_tmds0 : in STD_LOGIC;
clk_tmds90 : in STD_LOGIC;
clk_pixel : in STD_LOGIC;
red_p : in STD_LOGIC_VECTOR (7 downto 0);
green_p : in STD_LOGIC_VECTOR (7 downto 0);
blue_p : in STD_LOGIC_VECTOR (7 downto 0);
blank : in STD_LOGIC;
hsync : in STD_LOGIC;
vsync : in STD_LOGIC;
red_s : out STD_LOGIC;
green_s : out STD_LOGIC;
blue_s : out STD_LOGIC;
clock_s : out STD_LOGIC);
end dvid;
architecture Behavioral of dvid is
COMPONENT TDMS_encoder
PORT(
clk : IN std_logic;
data : IN std_logic_vector(7 downto 0);
c : IN std_logic_vector(1 downto 0);
blank : IN std_logic;
encoded : OUT std_logic_vector(9 downto 0)
);
END COMPONENT;
COMPONENT qdr
PORT(
clk0 : IN std_logic;
clk90 : IN std_logic;
data : IN std_logic_vector(3 downto 0);
qdr : OUT std_logic
);
END COMPONENT;
signal encoded_r, encoded_g, encoded_b : std_logic_vector(9 downto 0);
-- for the control frames (blanking)
constant c_red : std_logic_vector(1 downto 0) := (others => '0');
constant c_green : std_logic_vector(1 downto 0) := (others => '0');
signal c_blue : std_logic_vector(1 downto 0);
signal latched_r : std_logic_vector(9 downto 0) := (others => '0');
signal latched_g : std_logic_vector(9 downto 0) := (others => '0');
signal latched_b : std_logic_vector(9 downto 0) := (others => '0');
signal buffer_r : std_logic_vector(9 downto 0) := (others => '0');
signal buffer_g : std_logic_vector(9 downto 0) := (others => '0');
signal buffer_b : std_logic_vector(9 downto 0) := (others => '0');
-- one hot encoded. Initial Value is important to sync with pixel chantges!
signal state : std_logic_vector(4 downto 0) := "10000";
signal bits_r : std_logic_vector(3 downto 0) := (others => '0');
signal bits_g : std_logic_vector(3 downto 0) := (others => '0');
signal bits_b : std_logic_vector(3 downto 0) := (others => '0');
signal bits_c : std_logic_vector(3 downto 0) := (others => '0');
-- output shift registers
signal sr_r : std_logic_vector(11 downto 0):= (others => '0');
signal sr_g : std_logic_vector(11 downto 0):= (others => '0');
signal sr_b : std_logic_vector(11 downto 0):= (others => '0');
signal sr_c : std_logic_vector(9 downto 0) := "0111110000";
-- Gives a startup delay to allow the fifo to fill
signal delay_ctr : std_logic_vector(3 downto 0) := (others => '0');
begin
c_blue <= vsync & hsync;
TDMS_encoder_red: TDMS_encoder PORT MAP(clk => clk_pixel, data => red_p, c => c_red, blank => blank, encoded => encoded_r);
TDMS_encoder_green: TDMS_encoder PORT MAP(clk => clk_pixel, data => green_p, c => c_green, blank => blank, encoded => encoded_g);
TDMS_encoder_blue: TDMS_encoder PORT MAP(clk => clk_pixel, data => blue_p, c => c_blue, blank => blank, encoded => encoded_b);
qdr_r: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_r(3 downto 0), qdr => red_s);
qdr_g: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_g(3 downto 0), qdr => green_s);
qdr_b: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_b(3 downto 0), qdr => blue_s);
qdr_c: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_c(3 downto 0), qdr => clock_s);
process(clk_pixel)
begin
-- Just sample the encoded pixel data, to give a smooth transition to high speed domain
if rising_edge(clk_pixel) then
buffer_r <= encoded_r;
buffer_g <= encoded_g;
buffer_b <= encoded_b;
end if;
end process;
process(clk_tmds0)
begin
if rising_edge(clk_tmds0) then
bits_r <= sr_r(3 downto 0);
bits_g <= sr_g(3 downto 0);
bits_b <= sr_b(3 downto 0);
bits_c <= sr_c(3 downto 0);
case state is
when "00001" =>
sr_r <= "00" & latched_r;
sr_g <= "00" & latched_g;
sr_b <= "00" & latched_b;
when "00010" =>
sr_r <= "0000" & sr_r(sr_r'high downto 4);
sr_g <= "0000" & sr_g(sr_g'high downto 4);
sr_b <= "0000" & sr_b(sr_b'high downto 4);
when "00100" =>
sr_r <= latched_r & sr_r(5 downto 4);
sr_g <= latched_g & sr_g(5 downto 4);
sr_b <= latched_b & sr_b(5 downto 4);
when "01000" =>
sr_r <= "0000" & sr_r(sr_r'high downto 4);
sr_g <= "0000" & sr_g(sr_g'high downto 4);
sr_b <= "0000" & sr_b(sr_b'high downto 4);
when others =>
sr_r <= "0000" & sr_r(sr_r'high downto 4);
sr_g <= "0000" & sr_g(sr_g'high downto 4);
sr_b <= "0000" & sr_b(sr_b'high downto 4);
end case;
-- Move on to the next state
state <= state(state'high-1 downto 0) & state(state'high);
-- Move the TMDS clock signal shift register
sr_c <= sr_c(3 downto 0) & sr_c(sr_c'high downto 4);
if delay_ctr(delay_ctr'high) = '0' then
delay_ctr <= delay_ctr +1;
end if;
-- Move the encoded pixel data into the fast clock domain
latched_r <= buffer_r;
latched_g <= buffer_g;
latched_b <= buffer_b;
end if;
end process;
end Behavioral;
Take a look at this user guide which covers implementing HDMI on the atlys board as a reference design.
https://www.xilinx.com/support/documentation/application_notes/xapp495_S6TMDS_Video_Interface.pdf

VHDL State Machine Problems - Repeats States

We are building a processor for our final project. The control unit is a state machine, but it seems to get stuck in states for longer than it should, and thus it repeats instructions.
We are using Vivado 2015.4 and the Nexys4 board.
So, with a single line of instructions to store a value onto the 7-segments loaded up into the instruction memory, the states go:
Fetch =>
Fetch =>
Fetch =>
L_S_D (Load/Store Decode) =>
L_S_E (Load/Store Execute) =>
S_Mem (Store Memory Access) =>
Fetch =>
L_S_D =>
L_S_E =>
S_Mem =>
Fetch =>
L_S_D =>
L_S_E =>
Fetch (forever)
On the two complete run-throughs, the seven-segments display. On the third, incomplete run-through, they do not.
I'm attaching the state machine (relevant states) and the program counter-related code, because I think that's where the problem is.
State machine:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Fred is
Port ( Inst : in STD_LOGIC_vector (31 downto 21);
clk : in std_logic;
rst : in std_logic;
Reg2Loc : out std_logic;
ALUSRC : out std_logic;
MemtoReg : out std_logic;
RegWrite : out std_logic;
Branch : out std_logic;
ALUOp : out std_logic_vector (1 downto 0);
UnconB : out std_logic;
en : out std_logic;
wea : out std_logic;
PCWrite : out std_logic;
REGCEA : out std_logic;
LEDCode : out std_logic_vector (4 downto 0));
end Fred;
architecture Behavioral of Fred is
Type type_fstate is (Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
attribute enum_encoding : string;
attribute enum_encoding of type_fstate : type is "one-hot";
signal current_state : type_fstate;
signal next_state : type_fstate;
begin
clockprocess : process (clk, rst, current_state)
begin
if rst = '1' then
next_state <= Fetch;
elsif clk'EVENT and clk = '1' then
next_state <= current_state;
end if;
end process clockprocess;
state_logic: process (next_state)
begin
case next_state is
when Fetch => --00001
if ((Inst = "11111000010")) then --LDUR
current_state <= L_S_D;
elsif ((Inst = "11111000000")) then --STUR
current_state <= L_S_D;
--Additional State Logic Here
else
current_state <= Fetch;
end if;
when L_S_D => --00010
current_state <= L_S_E;
when L_S_E => --00011
if ((Inst = "11111000010")) then
current_state <= L_Mem;
elsif ((Inst = "11111000000")) then
current_state <= S_Mem;
end if;
when S_Mem => --00110
current_state <= Fetch;
--Additional States Here
when others =>
current_state <= Fetch;
end case;
end process state_logic;
output_logic : process (next_state)
begin
case next_state is
when Fetch =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '1';
LEDCode <= "00001";
when L_S_D =>
Reg2Loc <= '1';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00010";
when L_S_E =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '1';
REGCEA <= '0';
LEDCode <= "00011";
when S_Mem =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '1';
wea <= '1';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00110";
--Additional State Outputs Here
when others =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
end case;
end process output_logic;
end Behavioral;
Datapath:
entity Datapath is
Port (BTNClock : in STD_LOGIC;
clock : in STD_LOGIC;
UncondBranch : in STD_LOGIC;
CondBranch : in STD_LOGIC;
RRtwoSelect : in STD_LOGIC;
RegWriteSelect : in STD_LOGIC;
ALUSource : in STD_LOGIC;
ALUOpCode : in STD_LOGIC_VECTOR(1 downto 0);
WriteSelect : in STD_LOGIC;
MemWrite : in STD_LOGIC;
REGCEA : in STD_LOGIC;
PCWrite : in STD_LOGIC;
seg_select : out STD_LOGIC_vector(6 downto 0);
anode_select : out STD_LOGIC_vector(7 downto 0);
ins_out : out STD_LOGIC_VECTOR(31 downto 0);
RAMSelect : in STD_LOGIC;
ALUEleven : out STD_LOGIC;
REGEleven : out STD_LOGIC;
SwitchReset : in STD_LOGIC);
end Datapath;
architecture Behavioral of Datapath is
signal PC : STD_LOGIC_VECTOR(9 downto 0);
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal BranchSelect : STD_LOGIC;
signal ZeroBranch : STD_LOGIC;
signal RRtwo : STD_LOGIC_VECTOR(4 downto 0);
signal RegDataOut1 : STD_LOGIC_VECTOR(63 downto 0);
signal RegDataOut2 : STD_LOGIC_VECTOR(63 downto 0);
signal ALUMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal SignExtendOut : STD_LOGIC_VECTOR(63 downto 0);
signal BranchExtend : STD_LOGIC_VECTOR(9 downto 0);
signal ALUOut : STD_LOGIC_VECTOR(63 downto 0);
signal ALUZero : STD_LOGIC;
signal MemoryOut : STD_LOGIC_VECTOR(63 downto 0);
signal WriteMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal Branch : STD_LOGIC_VECTOR(9 downto 0);
signal PCNext : STD_LOGIC_VECTOR(9 downto 0);
signal PCIncrement : STD_LOGIC_VECTOR(9 downto 0);
signal ALUCommand : STD_LOGIC_VECTOR(3 downto 0);
signal InstEn : STD_LOGIC := '1';
signal OnlySeven : STD_LOGIC_VECTOR(0 downto 0);
signal SevSegReset : STD_LOGIC := '0';
begin
OnlySeven(0) <= MemWrite and not ALUOut(11);
BranchSelect <= UncondBranch or ZeroBranch;
ZeroBranch <= CondBranch and ALUZero;
ins_out <= instruction;
ALUEleven <= ALUout(11);
REGEleven <= RegDataOut1(11);
--Program Counter
PCReg : PCounter port map ( clk => BTNClock,
wea => PCWrite,
newaddress => PCNext,
thisaddress => PC);
--Incremental adder
IncAddr : B_adder port map ( a => PC,
x => PCIncrement);
--Branch Adder
BranchAddr : In_adder port map ( a => PC,
b => BranchExtend,
x => Branch);
--Next Instruction Address Mux
NextPCMux : nine_mux port map ( s => BranchSelect,
in1 => PCIncrement,
in2 => Branch,
output => PCNext);
--Additional Datapath Elements Here
end Behavioral;
Program Counter:
entity PCounter is
Port ( clk : in STD_LOGIC; --clock
wea : in STD_LOGIC; --write enable
newaddress : in STD_LOGIC_VECTOR (9 downto 0); --new address coming in
thisaddress : out STD_LOGIC_VECTOR (9 downto 0) --current address to be executed
);
end PCounter;
architecture Behavioral of PCounter is
signal reg: std_logic_vector(9 downto 0); --internal register storage
begin
process(clk) --nothing happens if this register isn't selected
begin
if clk'EVENT and clk = '1' then
thisaddress <= reg; --send out currently saved address
if wea = '1' then
reg <= newaddress; --and set register to next address
end if;
else
reg <= reg; --otherwise, maintain current value
end if;
end process;
end Behavioral;
This adder just adds one to the value currently in the PC:
entity B_adder is
Port ( a : in STD_LOGIC_VECTOR (9 downto 0);
x : out STD_LOGIC_VECTOR (9 downto 0));
end B_adder;
architecture Behavioral of B_adder is
begin
x <= a + 1;
end Behavioral;
This little mux will select if the next address is coming from the branch adder (not included here) or from the incremental adder above:
entity nine_mux is
Port ( s : in STD_LOGIC;
in1 : in STD_LOGIC_VECTOR (9 downto 0);
in2 : in STD_LOGIC_VECTOR (9 downto 0);
output : out STD_LOGIC_VECTOR (9 downto 0));
end nine_mux;
architecture Behavioral of nine_mux is
begin
with s select
output <= in1 when '0',
in2 when others;
end Behavioral;
And this is how the control unit is mapped to the datapath:
entity WholeThing is
Port ( BTNClock : in STD_LOGIC;
BTNReset : in STD_LOGIC;
SwitchReset : in STD_LOGIC;
clock : in STD_Logic;
LEDs : out STD_LOGIC_VECTOR(4 downto 0);
seg : out STD_LOGIC_vector(6 downto 0);
an : out STD_LOGIC_vector(7 downto 0);
alu11 : out STD_LOGIC;
reg11 : out STD_LOGIC
);
end WholeThing;
architecture Behavioral of WholeThing is
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal Reg2Loc : STD_LOGIC;
signal ALUSRC : std_logic;
signal MemtoReg : std_logic;
signal RegWrite : std_logic;
signal Branch : std_logic;
signal ALUOp : std_logic_vector (1 downto 0);
signal UnconB : std_logic;
signal en : std_logic;
signal wea : std_logic;
signal PCWrite : std_logic;
signal REGCEA : std_logic;
signal SwRst : STD_LOGIC;
begin
--SwitchReset <= SwRst;
--Control Unit
CU : Fred port map ( Inst => instruction(31 downto 21),
clk => BTNClock,
rst => BTNReset,
Reg2Loc => Reg2Loc,
ALUSRC => ALUSRC,
MemtoReg => MemtoReg,
RegWrite =>RegWrite,
Branch => Branch,
ALUOp => ALUOp,
UnconB => UnconB,
en => en,
wea => wea,
PCWrite => PCWrite,
REGCEA => REGCEA,
LEDCode => LEDs);
--Datapath
DP : Datapath port map (BTNClock => BTNClock,
clock => clock,
UncondBranch => UnconB,
CondBranch => Branch,
RRtwoSelect => Reg2Loc,
RegWriteSelect => RegWrite,
ALUSource => ALUSRC,
ALUOpCode => ALUOp,
WriteSelect => MemtoReg,
MemWrite => wea,
REGCEA => REGCEA,
PCWrite => PCWrite,
seg_select => seg,
anode_select => an,
ins_out => instruction,
RAMSelect => en,
ALUEleven => alu11,
REGEleven => reg11,
SwitchReset => SwitchReset
);
end Behavioral;
The FSM - the main problem
Your second process should implement default assignments to spare lots of unnecessary else branches where you define self-edged of your FSM graph. Because you missed that, your FSM creates additional latches for signal current_state! Check your synthesis report for latch warning and you might find multiple of them.
Other mistakes in the same file
You mixed up current_state and next_state. The meaning of the signals does not
reflect your code! Your case statement needs to switch on current_state.
Don't use the 3-process pattern to describe an FSM. This is a nightmare of code
readability and maintenance! One one can read and verify the behavior of this FSM form.
You're using the attribute enum_encoding in a wrong way:
to define an FSM encoding, apply fsm_encoding to the state signal
to define a user-defined encoding apply fsm_encoding with value user to your state signal and apply enum_encoding with a space separated list of binary values to your state type.
Don't use asynchronous reset. Synchronous, clocked processes have only one signal in the sensitivity list!
Combinational processes need to list all read signals in there sensitivity list!
You shouldn't use clk'EVENT and clk = '1'. Use rising_edge(clk) instead.
If you switch on the same signal multiple times, use a case statement, but no if-elsif construct!
Your eyes and probably also your LEDs will not be fast enough to see and display LEDCode.
Corrected code:
architecture Behavioral of Fred is
attribute fsm_encoding : string;
type type_fstate is (
Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
signal current_state : type_fstate := Fetch;
signal next_state : type_fstate;
attribute fsm_encoding of current_state : signal is "one-hot";
begin
clockprocess : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
current_state <= Fetch;
else
current_state <= next_state;
end if;
end if;
end process;
state_logic: process (current_state, Inst)
begin
next_state <= current_state;
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
case current_state is
when Fetch => --00001
REGCEA <= '1';
LEDCode <= "00001";
case Inst is
when "11111000010" => --LDUR
next_state <= L_S_D;
when "11111000000" => --STUR
next_state <= L_S_D;
--Additional State Logic Here
when others =>
next_state <= Fetch;
end case;
when L_S_D => --00010
Reg2Loc <= '1';
LEDCode <= "00010";
next_state <= L_S_E;
when L_S_E => --00011
Reg2Loc <= '1';
ALUSRC <= '1';
PCWrite <= '1';
LEDCode <= "00011";
case Inst is
when "11111000010" =>
next_state <= L_Mem;
when "11111000000" =>
next_state <= S_Mem;
when others =>
-- ???
end case;
when S_Mem => --00110
Reg2Loc <= '1';
ALUSRC <= '1';
en <= '1';
wea <= '1';
LEDCode <= "00110";
next_state <= Fetch;
--Additional States Here
when others =>
next_state <= Fetch;
end case;
end process;
end architecture;
Mistakes in the PC:
Never assign something like this reg <= reg in VHDL!
You're using arithmetic on type std_logic_vector. This operation is:
not defined for that type, or
you're using a non IEEE package like synopsys.std_logic_unsigned, which shouldn't be used at all. Use package ieee.numeric_std and types signed/unsigned if you need arithmetic operations.
Your program counter (PC) does not count (yet?). Based on the single responsibility principle, your PC should be able to:
load a new instruction pointer
increment an instruction pointer
output the current instruction pointer
Your PC assigns the output thisaddress with one cycle of delay. Normally, this will break any CPU functionality ...
As you're going to implement your design on an FPGA device, make sure to initialize all signals that are translated to memory (e.g. registers) with appropriate init values.
Improved Code:
architecture Behavioral of PCounter is
signal reg: unsigned(9 downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if wea = '1' then
reg <= unsigned(newaddress);
end if;
end if;
end process;
thisaddress <= reg;
end architecture;
Your adder B_adder
Is is wise to implement a one-line in an entity consuming 9 lines of code?
Moreover, your code is describing an incrementer, but not an adder.
Describing a Multiplexer
A Multiplexer is not described with a with ... select statement. This will create a priority logic like a chain of if-elseif branches.
output <= in1 when (s = '0') else in2;
As this is now a size independent one-liner, screw the nine_mux entity.

ALU implementation w/ ADDER

Hello I'm trying to create a 32-bit adder with a few opcodes and I've got it working quite well except for two cases and I can't seem to find what's causing them.. Maybe you can help me?
The subtraction case always fails for some reason and the ADDC case fails to compute the correct output when it should be using the carry bit in c_reg that has been created by the ADDS operation.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY ALU IS
GENERIC(WIDTH : NATURAL := 32);
PORT(Clk : IN STD_LOGIC := '0';
Reset : IN STD_LOGIC := '0';
A : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
B : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
Op : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
Outs : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END ALU;
ARCHITECTURE arch_ALU OF ALU IS
COMPONENT adder
PORT(OpA : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
OpB : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
Cin : IN STD_LOGIC;
Cout : OUT STD_LOGIC;
Result : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END COMPONENT;
SIGNAL adder_output : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL B_neg : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL c_flag : STD_LOGIC := '0';
SIGNAL c_reg : STD_LOGIC := '0';
SIGNAL cin : STD_LOGIC := '0';
BEGIN
adder_comp : adder
PORT MAP(OpA => A,
OpB => B_neg,
Cin => cin,
Result => adder_output,
Cout => c_flag);
WITH Op SELECT
B_neg <= NOT(B) WHEN "1000",
B WHEN OTHERS;
WITH Op SELECT
cin <= '1' WHEN "1000", -- SUB
c_reg WHEN "0111", -- ADDC
'0' WHEN OTHERS; -- ADD/ADDS
ALU_Process:
PROCESS(Clk)
BEGIN
IF Reset = '0' THEN
Outs <= (OTHERS => '0');
ELSIF rising_edge(Clk) THEN
CASE Op IS
WHEN "0001" => Outs <= A AND B;
WHEN "0010" => Outs <= A OR B;
WHEN "0011" => Outs <= A NOR B;
WHEN "0100" => Outs <= A XOR B;
WHEN "0101" => Outs <= adder_output; -- ADD
WHEN "0110" => Outs <= adder_output; -- ADDS
c_reg <= c_flag;
WHEN "0111" => Outs <= adder_output; -- ADDC
WHEN "1000" => Outs <= adder_output; -- SUB
WHEN "1001" => Outs <= STD_LOGIC_VECTOR(UNSIGNED(A) SLL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1010" => Outs <= STD_LOGIC_VECTOR(unsigned(A) SRL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1011" => Outs <= STD_LOGIC_VECTOR(shift_right(SIGNED(A),to_integer(UNSIGNED(B(4 DOWNTO 0)))));
WHEN OTHERS => Outs <= (OTHERS => '0');
END CASE;
END IF;
END PROCESS;
END arch_ALU;
Only the ADDS operation should write it's carry-out to the c_reg and ADDC operation should take the c_reg into account when calculating it's output
The adder is tested and working correctly so the problem is not in the adder design.
First of all I'd like to get to know the problem of the subtraction because it is doing subtraction but the result is a little bit off.. For example:
A : h'E6A4960F
B : h'7B494E34
Op : d'1000
Outs: h'6B5B47DA while it should be h'6B5B47DB
A : h'EFDE31A3
B : h'0BCAB8FA
Op : d'1000
Out : h'E41378BB while should be h'E41378A9
Can you spot my misstake? Cause I certainly can't..
While you didn't provide a Minimal, Complete, and Verifiable example the reader can at least test the subtract portions of your design that are present:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu is
generic (width: natural := 32);
port (
clk: in std_logic := '0';
reset: in std_logic := '0';
a: in std_logic_vector(width - 1 downto 0) := (others => '0');
b: in std_logic_vector(width - 1 downto 0) := (others => '0');
op: in std_logic_vector(3 downto 0) := (others => '0');
outs: out std_logic_vector(width - 1 downto 0)
);
end alu;
architecture arch_alu of alu is
-- component adder
-- port (
-- opa: in std_logic_vector(width - 1 downto 0);
-- opb: in std_logic_vector(width - 1 downto 0);
-- cin: in std_logic;
-- cout: out std_logic;
-- result: out std_logic_vector(width - 1 downto 0)
-- );
-- end component;
procedure adder (
signal opa: in std_logic_vector(width - 1 downto 0);
signal opb: in std_logic_vector(width - 1 downto 0);
signal cin: in std_logic;
signal cout: out std_logic;
signal result: out std_logic_vector(width - 1 downto 0)
) is
variable sum: unsigned (width downto 0);
begin
sum := unsigned('0' & opa) + unsigned(opb) + unsigned'(""& cin);
result <= std_logic_vector(sum (width - 1 downto 0));
cout <= sum(width);
end procedure;
signal adder_output: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b_neg: std_logic_vector(width - 1 downto 0) := (others => '0');
signal c_flag: std_logic := '0';
signal c_reg: std_logic := '0';
signal cin: std_logic := '0';
begin
adder_comp:
adder
-- port map (
(
opa => a,
opb => b_neg,
cin => cin,
result => adder_output,
cout => c_flag
);
with op select
b_neg <= not b when "1000",
b when others;
with op select
cin <= '1' when "1000", -- sub
c_reg when "0111", -- addc
'0' when others; -- add/adds
alu_process:
process(clk)
begin
if reset = '0' then
outs <= (others => '0');
elsif rising_edge(clk) then
case op is
when "0001" => outs <= a and b;
when "0010" => outs <= a or b;
when "0011" => outs <= a nor b;
when "0100" => outs <= a xor b;
when "0101" => outs <= adder_output; -- add
when "0110" => outs <= adder_output; -- adds
c_reg <= c_flag;
when "0111" => outs <= adder_output; -- addc
when "1000" => outs <= adder_output; -- sub
when "1001" => outs <= std_logic_vector (
unsigned(a) sll to_integer(unsigned(b(4 downto 0)))
);
when "1010" => outs <= std_logic_vector (
unsigned(a) srl to_integer(unsigned(b(4 downto 0)))
);
when "1011" => outs <= std_logic_vector (
shift_right(signed(a),to_integer(unsigned(b(4 downto 0))))
);
when others => outs <= (others => '0');
end case;
end if;
end process;
end arch_alu;
library ieee;
use ieee.std_logic_1164.all;
entity alu_tb is
end entity;
architecture foo of alu_tb is
constant width: integer := 32;
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal a: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b: std_logic_vector(width - 1 downto 0) := (others => '0');
signal op: std_logic_vector(3 downto 0) := (others => '0');
signal outs: std_logic_vector(width - 1 downto 0);
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 90 ns then
wait;
end if;
end process;
DUT:
entity work.alu
port map (
clk => clk,
reset => reset,
a => a,
b => b,
op => op,
outs => outs
);
STIMULUS:
process
begin
wait for 20 ns;
reset <= '1';
a <= x"E6A4960F";
b <= x"7B494E34";
op <= "1000";
wait for 20 ns;
a <= x"EFDE31A3";
b <= x"0BCAB8FA";
wait for 20 ns;
wait;
end process;
end architecture;
I wrote a quick and dirty procedure adder. This eliminates your adder entity/architecture and the component declaration.
I added a simple testbench for the two subtractions, this eliminates your test bench or testing procedure.
And this gives:
And as you can see the results are what you claim as correct.
So what that leaves is either your adder or your testbench (it's a stretch to blame your component declaration).
So what we get from this is that you haven't presented enough information to determine where the error is.
I did this little demonstration because the two errors don't have all the wrong bits in common. If you've tested your adder and are sure of it, it's probably the stimulus input when subtracting.

Resources