So I'm working on synthesizing a CPU.
These are the errors:
WARNING:Xst:1710 - FF/Latch <EXS/mem_address_0> (without init value) has a constant value of 0 in block <Top_level_component>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <EXS/mem_address_1> (without init value) has a constant value of 0 in block <Top_level_component>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <EXS/mem_address_2> (without init value) has a constant value of 0 in block <Top_level_component>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <EXS/mem_address_3> (without init value) has a constant value of 0 in block <Top_level_component>. This FF/Latch will be trimmed during the optimization process.
It then cascades onto a bunch of other stuff from here.
This is the part component that is giving me an error:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity EX_stage is
Port( clk : in STD_LOGIC;
rst : in STD_LOGIC;
mem_opr_in : in STD_LOGIC_VECTOR (1 downto 0);
wb_opr_in : in STD_LOGIC;
out_opr_in : in STD_LOGIC;
alu_mode : in STD_LOGIC_VECTOR (3 downto 0);
in1 : in STD_LOGIC_VECTOR (7 downto 0);
in2 : in STD_LOGIC_VECTOR (7 downto 0);
ra_in : in STD_LOGIC_VECTOR (1 downto 0);
-- The Ports I'm reading from
FW_opcode : in STD_LOGIC_VECTOR (3 downto 0);
FW_ra_IN : in STD_LOGIC_VECTOR (1 downto 0);
FW_rb_IN : in STD_LOGIC_VECTOR (1 downto 0);
-- The port I'm writing to
mem_address : out STD_LOGIC_VECTOR (7 downto 0);
mem_opr_out : out STD_LOGIC_VECTOR (1 downto 0);
wb_opr_out : out STD_LOGIC;
out_opr_out : out STD_LOGIC;
alu_result : out STD_LOGIC_VECTOR (7 downto 0);
alu_mode_out : out STD_LOGIC_VECTOR (3 downto 0);
ra_out : out STD_LOGIC_VECTOR (1 downto 0);
z_flag : out STD_LOGIC;
n_flag : out STD_LOGIC);
end EX_stage;
architecture Behavioral of EX_stage is
begin
process(clk,rst)
variable temp_result: STD_LOGIC_VECTOR (7 downto 0);
begin
-- Not important... I think
end process;
process(clk,rst)
begin
if rst = '1' then
mem_address <= (others => '0');
elsif clk = '1' and clk'event then
mem_address <= FW_opcode & FW_ra_IN & FW_rb_IN;
-- If this is <= x"FF"; then it doesn't give the error
end if;
end process;
end Behavioral;
In the top level component I have:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Top_level_component is
Port ( portIN : in STD_LOGIC_VECTOR (7 downto 0);
portOUT : out STD_LOGIC_VECTOR (7 downto 0);
clk : in STD_LOGIC;
rst : in STD_LOGIC);
end Top_level_component;
architecture Behavioral of Top_level_component is
-- Only the offending components shown
component IF_stage
port( clk : in STD_LOGIC;
rst : in STD_LOGIC;
count : in STD_LOGIC_VECTOR (7 downto 0);
-- All three of these get input to ID_stage AND EX_stage
opcode : out STD_LOGIC_VECTOR (3 downto 0);
reg_a : out STD_LOGIC_VECTOR (1 downto 0);
reg_b : out STD_LOGIC_VECTOR (1 downto 0));
end component;
component ID_stage is
port( clk : in STD_LOGIC;
port_IN : in STD_LOGIC_VECTOR (7 downto 0);
opcode : in STD_LOGIC_VECTOR (3 downto 0);
ra_IN : in STD_LOGIC_VECTOR (1 downto 0);
rb_IN : in STD_LOGIC_VECTOR (1 downto 0);
zflag : in STD_LOGIC;
nflag : in STD_LOGIC;
RD1_IN : in STD_LOGIC_VECTOR (7 downto 0);
RD2_IN : in STD_LOGIC_VECTOR (7 downto 0);
count : in STD_LOGIC_VECTOR (7 downto 0);
previous_opcode : in STD_LOGIC_VECTOR (3 downto 0);
MEM_opr : out STD_LOGIC_VECTOR (1 downto 0);
WB_opr : out STD_LOGIC;
OUT_opr : out STD_LOGIC;
ALU_mode : out STD_LOGIC_VECTOR (3 downto 0);
RD1_OUT : out STD_LOGIC_VECTOR (7 downto 0);
RD2_OUT : out STD_LOGIC_VECTOR (7 downto 0);
ra_OUT : out STD_LOGIC_VECTOR (1 downto 0);
rb_OUT : out STD_LOGIC_VECTOR (1 downto 0);
new_count : out STD_LOGIC_VECTOR (7 downto 0);
set_pc : out STD_LOGIC);
end component;
component EX_stage is
port( clk : in STD_LOGIC;
rst : in STD_LOGIC;
mem_opr_in : in STD_LOGIC_VECTOR (1 downto 0);
wb_opr_in : in STD_LOGIC;
out_opr_in : in STD_LOGIC;
alu_mode : in STD_LOGIC_VECTOR (3 downto 0);
in1 : in STD_LOGIC_VECTOR (7 downto 0);
in2 : in STD_LOGIC_VECTOR (7 downto 0);
ra_in : in STD_LOGIC_VECTOR (1 downto 0);
-- The Offending ports: This is where the signals go in
FW_opcode : in STD_LOGIC_VECTOR (3 downto 0);
FW_ra_IN : in STD_LOGIC_VECTOR (1 downto 0);
FW_rb_IN : in STD_LOGIC_VECTOR (1 downto 0);
mem_address : out STD_LOGIC_VECTOR (7 downto 0);
mem_opr_out : out STD_LOGIC_VECTOR (1 downto 0);
wb_opr_out : out STD_LOGIC;
out_opr_out : out STD_LOGIC;
alu_result : out STD_LOGIC_VECTOR (7 downto 0);
alu_mode_out : out STD_LOGIC_VECTOR (3 downto 0);
ra_out : out STD_LOGIC_VECTOR (1 downto 0);
z_flag : out STD_LOGIC;
n_flag : out STD_LOGIC);
end component;
-- Signals used
signal set_pc : STD_LOGIC := '0';
signal new_count : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal count : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal IF_opcode : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
signal IF_reg_a : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal IF_reg_b : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal rd_data1 : std_logic_vector(7 downto 0) := (others => '0');
signal rd_data2 : std_logic_vector(7 downto 0) := (others => '0');
signal ID_opcode : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
signal ID_reg_a : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal ID_reg_b : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal ID_data1 : std_logic_vector(7 downto 0) := (others => '0');
signal ID_data2 : std_logic_vector(7 downto 0) := (others => '0');
signal ID_mem_opr : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal ID_wb_opr : STD_LOGIC := '0';
signal ID_out_opr : STD_LOGIC := '0';
signal EX_data1 : std_logic_vector(7 downto 0) := (others => '0');
signal EX_data2 : std_logic_vector(7 downto 0) := (others => '0');
signal EX_reg_a : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal EX_results : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal EX_alu_mode : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
signal mem_address : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal EX_mem_opr : STD_LOGIC_VECTOR (1 downto 0) := (others => '0');
signal EX_wb_opr : STD_LOGIC := '0';
signal EX_out_opr : STD_LOGIC := '0';
signal z_flag : std_logic := '0';
signal n_flag : std_logic := '0';
begin
IFS: IF_stage PORT MAP(
clk => clk,
rst => rst,
count => count,
opcode => IF_opcode,
reg_a => IF_reg_a,
reg_b => IF_reg_b);
IDS: ID_stage port map(
clk => clk,
port_IN => portIN,
opcode => IF_opcode,
ra_IN => IF_reg_a,
rb_IN => IF_reg_b,
zflag => z_flag,
nflag => n_flag,
RD1_IN => rd_data1,
RD2_IN => rd_data2,
count => count,
previous_opcode => EX_alu_mode,
MEM_opr => ID_mem_opr,
WB_opr => ID_wb_opr,
OUT_opr => ID_out_opr,
ALU_mode => ID_opcode,
RD1_OUT => ID_data1,
RD2_OUT => ID_data2,
ra_OUT => ID_reg_a,
rb_OUT => ID_reg_b,
new_count => new_count,
set_pc => set_pc);
EXS: EX_stage port map(
clk => clk,
rst => rst,
mem_opr_in => ID_mem_opr,
wb_opr_in => ID_wb_opr,
out_opr_in => ID_out_opr,
alu_mode => ID_opcode,
in1 => EX_data1,
in2 => EX_data2,
ra_in => ID_reg_a,
FW_opcode => IF_opcode,
FW_ra_IN => IF_reg_a,
FW_rb_IN => IF_reg_b,
mem_address => mem_address,
mem_opr_out => EX_mem_opr,
wb_opr_out => EX_wb_opr,
out_opr_out => EX_out_opr,
alu_result => EX_results,
alu_mode_out => EX_alu_mode,
ra_out => EX_reg_a,
z_flag => z_flag,
n_flag => n_flag);
end Behavioral;
So in the EX_stage, when using FW_opcode, FW_ra_IN, or FW_rb_IN, I get the errors. I Don't get it. Any Ideas? Is it that I'm trying to merge the inputs into an output?
That is not an error. It is a warning saying that the synthesizer has detected that the signal will always be 0, and that it can thus be optimized out.
Also, it has nothing to do with a latch being created as your title says (notice that the wording is FF/Latch, which just says that the signal EXS/mem_address_0 is either a flip-flop or a latch).
This is not necessarily a bad thing, unless you know that they should also be able to take on other values.
In this case, I'd say it seems as if your FW_ra_IN and FW_rb_IN signals are always 0. If they should be able to take on other values, then make sure that they are actually sourced from the correct place.
The reason why you don't get the warnings when replacing the assignment with x"FF" is that you then have the signal being all 0 when under reset, and all 1 when not - and none of the bits are thus constant.
Also have a look at VHDL synthesis warning FF/Latch has a constant value of 0
first of all, what you posted are warnings and not errors... should therefore be nonblocking.
however, the warnings tell you, that mem_address(3..0) has values that are always '0'. this means, that FW_ra_IN and FW_rb_IN is always '0'. these signals come from your IF_stage block (IF_reg_a and IF_reg_b). check, whether you update these signals within IF_stage or not.
another thing is, that mem_address is not used within top_level block. it might therefore be removed by the synthesizer during optimization.
Related
I am coding a 16-bit CPU for a school project and I've run into an issue that has dumbfounded me. The first three steps of my clock cycle are naturally to increment the program counter and load a new instruction into the instruction register. So the problem; the value in the program counter increments as expected but stalls at 6 for several cycles then picks up again and stalls at 12 for several more, again at 18 and then 24, this is as far as I've let it run, I assume it'll persist at succeeding multiples of six. I dunno if it is something to do with the way VHDL treats signed values, I edited the ALU code to achieve this by adding one to the Program Counter value instead of incrementing but there was no change, I changed the ALUs representation of the values to unsigned but that didn't help and I honestly cannot see why it would. My code is as follows:
library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity CPU_1 is
port( prim_clk : in std_logic;
achtung : out std_logic_vector(15 downto 0) ;
HEX0, HEX1, HEX2 : out std_logic_vector(6 downto 0));
end CPU_1;
Architecture behaviour of Nandos is
signal sys_clk, clk, cu_s, cu_e: std_logic;
signal step : std_logic_vector(5 downto 0);
signal acc_ena, acc_set, pc_set, pc_ena: std_logic := 'Z';
signal data_bus, alu_acc : std_logic_vector(15 downto 0);--M_addr_bus,
component Clock
port( clk : in std_logic; --50 MHz
clk_s : out std_logic;--set data clk
clk_e : out std_logic);--enable data(on bus) clk
end component;
component Control_Unit
port( sys_clk, clk_s, clk_e : in std_logic;
acc_ena, acc_set, pc_set, pc_ena: out std_logic;
stepp : out std_logic_vector(5 downto 0));
end component;
component program_Counter
port( clk: in std_logic;
set, en : in std_logic;
pc_in : in std_logic_vector(15 downto 0);
pc_out : out std_logic_vector(15 downto 0));
end component;
component ALU
port( clk: in std_logic;
d1 : in std_logic_vector(15 downto 0);
d3 : out std_logic_vector(15 downto 0));
end component;
component accumulator
port( clk: in std_logic;
frm_ALU: in std_logic_vector(15 downto 0);
acc_set, acc_ena : in std_logic;
to_bus : out std_logic_vector(15 downto 0));
end component;
begin
HEX2(5 downto 0) <= step;--serves to demonstrate on the board that it is running
achtung <= data_bus;--debug what is on the bus
clk0 : Clock port map(prim_clk, cu_s, cu_e);
cu0 : Control_Unit port map(prim_clk, cu_s, cu_e, acc_ena, acc_set, pc_set, pc_ena, step);
p_c : program_Counter port map(prim_clk, pc_set, pc_ena, data_bus, data_bus);
alu0 : ALU port map(prim_clk, data_bus, alu_acc);
acc : accumulator port map(prim_clk, alu_acc, acc_set, acc_ena, data_bus);
end behaviour;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Control_Unit is
port( sys_clk, clk_s, clk_e : in std_logic;
acc_ena, acc_set, pc_set, pc_ena: out std_logic;
stepp : out std_logic_vector(5 downto 0)); --just to ko
end Control_Unit;
architecture behaviour of Control_Unit is
signal step : std_logic_vector(5 downto 0);
component Stepper
port( clk : in std_logic;
step : out std_logic_vector(5 downto 0));
end component;
begin
stpr : Stepper port map(sys_clk, step);
stepp <= step;
process(sys_clk, step)
begin
if rising_edge(sys_clk) then
if step(0) = '1' then
case clk_s is
when '1' =>
acc_set <= '1';
when '0' =>
acc_set <= '0';
end case;
case clk_e is
when '1' =>
pc_ena <= '1';
when '0' =>
pc_ena <= '0';
end case;
elsif step(1) = '1' then
case clk_s is
when '1' =>
null;
when '0' =>
null;
end case;
case clk_e is
when '1' =>
null;
when '0' =>
null;
end case;
elsif step(2) = '1' then
case clk_s is
when '1' =>
pc_set <= '1';
when '0' =>
pc_set <= '0';
end case;
case clk_e is
when '1' =>
acc_ena <= '1';
when '0' =>
acc_ena <= '0';
end case;
end if;
end if;
end process;
end behaviour;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY ALU IS
port( clk: in std_logic;
d1: in std_logic_vector(15 downto 0);
d3 : out std_logic_vector(15 downto 0));
END ALU;
ARCHITECTURE behaviour OF ALU IS
signal Zsig: signed(15 downto 0);
begin
process(clk, d1)
begin
if rising_edge(clk) then
Zsig <= signed(d1) + 1;
end if;
end process;
d3 <= std_logic_vector(signed(Zsig));
end behaviour;
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity Clock is
port( clk :in std_logic;
clk_s : out std_logic;
clk_e : out std_logic);
end Clock;
--slowing down the clock so I can track data flow.
architecture Behavioral of Clock is
signal count: integer := 1;
signal clock_1: std_logic := '1';
signal clock_2: std_logic := '0';
begin
process(clk)
begin
if rising_edge(clk) then
count <= count + 1;
if count = 12500000 then --10
clock_1 <= not clock_1;
count <= 1;
elsif count = 5000000 then--4
clock_2 <= not clock_2;
end if;
end if;
end process;
clk_e <= clock_1 or clock_2;
clk_s <= clock_1 and clock_2;
end Behavioral;
library ieee;
use ieee.std_logic_1164.all;
entity stepper is
port (clk : in std_logic;
step: out std_logic_vector(5 downto 0));
end stepper;
architecture behav of stepper is
signal count : integer := 0;
begin
Process(clk)
begin
if rising_edge(clk) then
count <= count+1;
if count = 0 then --0
step <= "000001";
elsif count = 23750000 then --19
step <= "000010";
elsif count = 48750000 then --39
step <= "000100";
elsif count = 73750000 then --59
step <= "001000";
elsif count = 98750000 then --79
step <= "010000";
elsif count = 123750000 then --99
step <= "100000";
elsif count = 148750000 then --119
count <= 0;
end if;
end if;
end Process;
end behav;
library IEEE;
use ieee.std_logic_1164.all;
entity program_Counter is
port( clk: in std_logic;
set, en : in std_logic;
pc_in : in std_logic_vector(15 downto 0);
pc_out : out std_logic_vector(15 downto 0));
end program_Counter;
Architecture behaviour of program_Counter is
signal RAM : std_logic_vector(15 downto 0);
begin
process(clk, RAM, set, en)
begin
if rising_edge(clk) then
if set = '1' then
RAM <= pc_in;
elsif en = '1' then
pc_out <= RAM;
else
pc_out <= "ZZZZZZZZZZZZZZZZ";
end if;
end if;
end process;
end behaviour;
library IEEE;
use ieee.std_logic_1164.all;
entity accumulator is
port( clk: in std_logic;
frm_ALU: in std_logic_vector(15 downto 0);
acc_set, acc_ena : in std_logic;
to_bus : out std_logic_vector(15 downto 0));
end accumulator;
Architecture behaviour of accumulator is
signal RAM : std_logic_vector(15 downto 0);
begin
process(clk, acc_set, acc_ena, RAM)
begin
if rising_edge(clk) then
if acc_set = '1' then
RAM <= frm_ALU;
elsif acc_ena = '1' then
to_bus <= RAM;
else
to_bus <= "ZZZZZZZZZZZZZZZZ";
end if;
end if;
end process;
end behaviour;
Sorry for what must be riddled with coding taboos. I feel I should point out that when I originally wrote the code it ran fine with an ADD instruction, I changed it to increment for simplification and didn't run into any problems that I can remember. Several additions later I start getting this error so I strip everything else down to bare bones, removing registers and such but here the error still is.
I use the Quartus II 13.0 software to code and an Altera DE2 EP2C35F672C6 to run the code. Thank you.
I found the problem, after preloading the program counter with the value for 5 and not immediately running into the error when it tried to increment 6 to 7 but instead at 11 it became clear that the logic was not the culprit. The steppers first stage lasts a little shorter than the others(1250000 ticks to be exact) and it desyncs after 6 cycles, after a few more cycles it syncs up again, runs correctly and desyncs again after 6 more. This has been resolved and the counter now increments endlessly, as desired.
I am using Vivado 2014.2 to write VHDL code for a BCD to Binary input buffer that could be used for a calculator or a combo lock.
My method is simple. to do x*10 it is the same as x(2 + 8) = x*2 + x*8.
x*2 = 1 left shift (2^1 = 2)
x*8 = 3 left shifts (2^3 = 8)
The output buffer(tempC) is shifted and added before the input is added. This is done so that when starting from null so that the first digit entered doesn't come out multiplied by 10.
My code compiles and runs on an artix 7 fpga, but I am having issues making sure that the output buffer(tempC) is working correctly. It refuses to output any data, but I am not sure why.
I could be adding the values together wrong but I dont think its that. Maybe i'm casting to a wrong data type?
Any help is greatly appreciated.
-- Engineer: greatgamer34
--
-- Create Date: 01/25/2017 04:57:02 PM
-- Design Name:
-- Module Name: buff - Behavioral
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity buff is
Port ( Data : in STD_LOGIC_VECTOR (3 downto 0); ----4bit BCD value input
Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Output : out STD_LOGIC_VECTOR (15 downto 0);
aout : out STD_LOGIC_VECTOR (6 downto 0));-- 7 segment display output for current state.
end buff;
architecture Behavioral of buff is
type states is (state0, state1, state2, state3);
signal currentstate, nextstate: states;
signal tempA: STD_LOGIC_VECTOR (15 downto 0);---used to store 'Data' for addition.
signal tempB: STD_LOGIC_VECTOR (15 downto 0);---used for x2('Data').
signal tempC: STD_LOGIC_VECTOR (15 downto 0);---used as output register.
signal tempD: STD_LOGIC_VECTOR (15 downto 0);---used for sending data to LED's.
signal tempE: STD_LOGIC_VECTOR (15 downto 0);---used for x8('Data')
begin
Process(Reset,clock)
Begin
if(Reset = '1') then
tempC <= "0000000000000000"; --clear tempC
tempA <= "0000000000000000"; --clear tempA
currentstate <= state0; -------reset state to 0
elsif(clock'event and clock = '1') then
output <= (tempD);--dispaly the output of the buffer
currentstate<=nextstate; -- advance states
end if;
end process;
process(currentstate)
begin
case currentstate is
when state0 =>
tempA(3 downto 0) <= Data; -- load in 4 bit data intoi 16 bit register
tempD <= (tempA); --output the input data(used for debugging)
nextstate <= state1;
aout <= not "1111110"; -- output on the 7 seg the number 0
when state1 =>
tempB <= tempC(14 downto 0) & '0'; --left shift tempC(the output register) save to tempB; this is the x2 multiplication
tempD <= (tempA); -- output the input data(used for debugging)
nextstate <= state2;
aout <= not "0110000"; -- output on the 7 seg the number 1
when state2 =>
tempE <= tempC(12 downto 0) & "000"; --left shift tempC(the output register) three times save to tempE; this is the x8 multiplication
--tempC <=std_logic_vector( unsigned(tempE) + unsigned(tempD)); (TESTING)
tempC <=std_logic_vector( ('0' & unsigned(tempE(14 downto 0))) + ('0' & unsigned(tempD(14 downto 0)))); --add the first 15 bits of tempD and tempE(this is how we multiply by 10)
tempD <= (tempC); -- output the x10 output register
nextstate <= state3;
aout <= not "1101101" ; -- output on the 7 seg the number2
when state3 =>
-- tempC <= ('0' & tempC(14 downto 0)) + ('0' & tempA(14 downto 0)); (TESTING)
tempC <= std_logic_vector( ('0' & unsigned(tempC(14 downto 0))) + ('0' & unsigned(tempA(14 downto 0)))); --add the 'Data' to the x10 shifted number.
tempD <= (tempC);
nextstate <= state0;
aout <= not "1111001"; -- output on the 7 seg the number3
end case;
end process;
end behavioral;
Answer:
tempC is reset in the clocked process and then gets new values assigned in the combinatorial process.
It is not allowed to assign a signals a value in two different processes. Also the sensitivity list of the combinatorial process is missing signals.
Observations:
Use logical names for your signals tempX is very confusing. Also I cant imagine that your BCD circuit will be called BUFF ;)
Check the sensitivity list of your combinatoric process.
Google on how a state machine needs to be constructed
Simulation of your design in very important (especially for larger designs)
have a look at the different tutorials online eg Xilinx Vivado
2015.2 Simulation Tutorial
Happy debugging
Okay with help from some of the comments and answers I was able to get it to work. The following is the code used.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity buff is
Port ( Data : in STD_LOGIC_VECTOR (3 downto 0); ----4bit BCD value input
Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Output : out STD_LOGIC_VECTOR (15 downto 0);
aout : out STD_LOGIC_VECTOR (6 downto 0));-- 7 segment display output for current state.
end buff;
architecture Behavioral of buff is
type states is (state0, state1, state2, state3, state4);
signal currentstate, nextstate: states;
signal tempA: STD_LOGIC_VECTOR (3 downto 0);---used to store 'Data' for addition.
signal tempB: STD_LOGIC_VECTOR (15 downto 0);---used for x2('Data').
signal tempC: STD_LOGIC_VECTOR (15 downto 0);---used as output register.
signal tempD: STD_LOGIC_VECTOR (15 downto 0);---used for sending data to LED's.
signal tempE: STD_LOGIC_VECTOR (15 downto 0);---used for x8('Data')
signal tempF: STD_LOGIC_VECTOR (15 downto 0);
begin
Process(Reset,clock)
Begin
if(Reset = '1') then
currentstate <= state4;
Output <= "0000000000000000"; -------reset state
elsif(clock'event and clock = '1') then
Output <= tempD ;--display the output of the buffer
currentstate <= nextstate; -- advance states
end if;
end process;
process(currentstate)
begin
case currentstate is
when state0 =>
tempA <= Data; -- load in 4 bit data intoi 16 bit register
tempD(3 downto 0) <= tempA; --output the input data(used for debugging)
nextstate <= state1;
aout <= not "1111110"; -- output on the 7 seg the number 0
when state1 =>
tempB <= (tempC(14 downto 0) & "0"); --left shift tempC(the output register) save to tempB; this is the x2 multiplication
tempD <= (tempB); -- output the input data(used for debugging)
nextstate <= state2;
aout <= not "0110000"; -- output on the 7 seg the number 1
when state2 =>
tempE <= tempC(12 downto 0) & "000"; --left shift tempC(the output register) three times save to tempE; this is the x8 multiplication
--tempF <=std_logic_vector( unsigned(tempE) + unsigned(tempB)); --(TESTING)
tempF <=std_logic_vector( ('0' & unsigned(tempE(14 downto 0))) + ('0' & unsigned(tempB(14 downto 0)))); --add the first 15 bits of tempD and tempE(this is how we multiply by 10)
tempD <= tempE; -- output the x10 output register
nextstate <= state3;
aout <= not "1101101" ; -- output on the 7 seg the number2
when state3 =>
--tempC <=std_logic_vector( unsigned(tempC) + unsigned(tempA));
tempC <= std_logic_vector( ('0' & unsigned(tempF(14 downto 0))) + ("000000000000" & unsigned(tempA))); --add the 'Data' to the x10 shifted number.
tempD <= tempC;
nextstate <= state0;
aout <= not "1111001"; -- output on the 7 seg the number3
when state4 =>
tempC <= "0000000000000000";
tempA <= "0000";
tempB <= "0000000000000000";
tempD <= "0000000000000000";
tempE <= "0000000000000000";
tempF <= "0000000000000000";
nextstate <= state0;
aout <= not "0110011";
end case;
end process;
end behavioral;
The algorithm is well known, you do 8 left shifts and check the units, tens or hundreds bits (4 each) after each shift. If they are above 4 you add 3 to the group and so on...
Here is a process based solution that does not work. It will compile but the output is not what I wanted. Any thoughts what could be the problem?
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;
entity hex2bcd is
port ( hex_in : in std_logic_vector (7 downto 0) ;
bcd_hun : out std_logic_vector (3 downto 0) ;
bcd_ten : out std_logic_vector (3 downto 0) ;
bcd_uni : out std_logic_vector (3 downto 0) ) ;
end hex2bcd ;
architecture arc_hex2bcd of hex2bcd is
begin
process ( hex_in )
variable hex_src : std_logic_vector (7 downto 0) ;
variable bcd : std_logic_vector (11 downto 0) ;
begin
hex_src := hex_in ;
bcd := (others => '0') ;
for i in 0 to 7 loop
bcd := bcd(11 downto 1) & hex_src(7) ; -- shift bcd + 1 new entry
hex_src := hex_src(7 downto 1) & '0' ; -- shift src + pad with 0
if bcd(3 downto 0) > "0100" then
bcd(3 downto 0) := bcd(3 downto 0) + "0011" ;
end if ;
if bcd(7 downto 4) > "0100" then
bcd(7 downto 4) := bcd(7 downto 4) + "0011" ;
end if ;
if bcd(11 downto 8) > "0100" then
bcd(11 downto 8) := bcd(11 downto 8) + "0011" ;
end if ;
end loop ;
bcd_hun <= bcd(11 downto 8) ;
bcd_ten <= bcd(7 downto 4) ;
bcd_uni <= bcd(3 downto 0) ;
end process ;
end arc_hex2bcd ;
The comments were getting too long.
Consider the following block diagram:
This represents an unrolled loop (for i in 0 to 7 loop) and shows that no add +3 occurs before i = 2 for the LS BCD digit and no add +3 occurs before i = 5 for the middle BCD digit, and no adjustment occurs on the MS BCD digit, which is comprise in part of static '0' values.
This gives us a total of 7 add3 modules (represented by the enclosing if statement, and conditional add +3).
This is demonstrated in VHDL:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bin8bcd is
port (
bin: in std_logic_vector (7 downto 0);
bcd: out std_logic_vector (11 downto 0)
);
end entity;
architecture struct of bin8bcd is
procedure add3 (signal bin: in std_logic_vector (3 downto 0);
signal bcd: out std_logic_vector (3 downto 0)) is
variable is_gt_4: std_logic;
begin
is_gt_4 := bin(3) or (bin(2) and (bin(1) or bin(0)));
if is_gt_4 = '1' then
-- if to_integer(unsigned (bin)) > 4 then
bcd <= std_logic_vector(unsigned(bin) + "0011");
else
bcd <= bin;
end if;
end procedure;
signal U0bin,U1bin,U2bin,U3bin,U4bin,U5bin,U6bin:
std_logic_vector (3 downto 0);
signal U0bcd,U1bcd,U2bcd,U3bcd,U4bcd,U5bcd,U6bcd:
std_logic_vector (3 downto 0);
begin
U0bin <= '0' & bin (7 downto 5);
U1bin <= U0bcd(2 downto 0) & bin(4);
U2bin <= U1bcd(2 downto 0) & bin(3);
U3bin <= U2bcd(2 downto 0) & bin(2);
U4bin <= U3bcd(2 downto 0) & bin(1);
U5bin <= '0' & U0bcd(3) & U1bcd(3) & U2bcd(3);
U6bin <= U5bcd(2 downto 0) & U3bcd(3);
U0: add3(U0bin,U0bcd);
U1: add3(U1bin,U1bcd);
U2: add3(U2bin,U2bcd);
U3: add3(U3bin,U3bcd);
U4: add3(U4bin,U4bcd);
U5: add3(U5bin,U5bcd);
U6: add3(U6bin,U6bcd);
OUTP:
bcd <= '0' & '0' & U5bcd(3) & U6bcd & U4bcd & bin(0);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bin8bcd_tb is
end entity;
architecture foo of bin8bcd_tb is
signal bin: std_logic_vector (7 downto 0) := (others => '0');
-- (initialized to prevent those annoying metavalue reports)
signal bcd: std_logic_vector (11 downto 0);
begin
DUT:
entity work.bin8bcd
port map (
bin => bin,
bcd => bcd
);
STIMULUS:
process
begin
for i in 0 to 255 loop
bin <= std_logic_vector(to_unsigned(i,8));
wait for 1 ns;
end loop;
wait for 1 ns;
wait;
end process;
end architecture;
That when the accompanying test bench is run yields:
And if you were to scroll through the entire waveform you'd find that all bcd outputs from 001 to 255 are present and accounted for (no holes), no 'X's or 'U's anywhere.
From the representation in the block diagram showing i = 7 we see that no add +3 occurs after the final shift.
Also note that the LSB of bcd is always the LSB of bin, and that bcd(11) and bcd(10) are always '0'.
The add3 can be hand optimized to create an increment by 3 using logic operators to get rid of any possibility of reporting meta values derived from bin (and there'd be a lot of them).
As far as I can tell this represents the most optimized representation of 8 bit binary to 12 bit BCD conversion.
Sometime previously I wrote a C program to provide input to espresso (a term minimizer):
/*
* binbcd.c - generates input to espresso for 8 bit binary
* to 12 bit bcd.
*
*/
#include <stdlib.h>
#include <stdio.h>
int main (argc, argv)
int argc;
char **argv;
{
int binary;
int bit;
char bcd_buff[4];
int digit;
int bcd;
printf(".i 8\n");
printf(".o 12\n");
for (binary = 0; binary < 256; binary++) {
for ( bit = 7; bit >= 0; bit--) {
if ((1 << bit) & binary)
printf("1");
else
printf("0");
}
digit = snprintf(bcd_buff,4,"%03d",binary); /* leading zeros */
if (digit != 3) {
fprintf(stderr,"%s: binary to string conversion failure, digit = %d\n",
argv[0],digit);
exit (-1);
}
printf (" "); /* input to output space */
for ( digit = 0; digit <= 2; digit++) {
bcd = bcd_buff[digit] - 0x30;
for (bit = 3; bit >= 0; bit--) {
if ((1 << bit) & bcd)
printf("1");
else
printf("0");
}
}
/* printf(" %03d",binary); */
printf("\n");
}
printf (".e\n");
exit (0);
Then started poking around with intermediary terms, which leads you directly to what is represented in the block diagram above.
And of course you could use an actual component add3 as well as use nested generate statements to hook everything up.
You won't get the same minimized hardware from a loop statement representation without constraining the if statements (2 < i < 7 for the LS BCD digit, 5 < i < 7 for the middle BCD digit).
You'd want the subsidiary nested generate statement to provide the same constraints for a shortened structural representation.
A logic operator version of add3 is shown on PDF page 5 on the university lecture slides for Binary to BCD Conversion using double dabble, where the forward tick is used for negation notation, "+" signifies OR, and Adjacency signifies AND.
The add3 then looks like:
procedure add3 (signal bin: in std_logic_vector (3 downto 0);
signal bcd: out std_logic_vector (3 downto 0)) is
begin
bcd(3) <= bin(3) or
(bin(2) and bin(0)) or
(bin(2) and bin(1));
bcd(2) <= (bin(3) and bin(0)) or
(bin(2) and not bin(1) and not bin(0));
bcd(1) <= (bin(3) and not bin(0)) or
(not bin(2) and bin(1)) or
(bin(1) and bin(0));
bcd(0) <= (bin(3) and not bin(0)) or
(not bin(3) and not bin(2) and bin(0)) or
(bin(2) and bin(1) and not bin(0));
end procedure;
Note this would allow package numeric_std (or equivalent) to be dropped from the context clause.
If you write signals in AND terms in the same order (in this case left to right) the duplicated AND terms show up well, as the also do using espresso. There is no value in using intermediary AND terms in an FPGA implementation, these all fit it LUTs just the way they are.
espresso input for add3:
.i 4
.o 4
0000 0000
0001 0001
0010 0010
0011 0011
0100 0100
0101 1000
0110 1001
0111 1010
1000 1011
1001 1100
1010 ----
1011 ----
1100 ----
1101 ----
1110 ----
1111 ----
.e
And espresso's output (espresso -eonset):
.i 4
.o 4
.p 8
-100 0100
00-1 0001
--11 0010
-01- 0010
-110 1001
-1-1 1000
1--1 1100
1--0 1011
.e
When you consider the combinatorial 'depth' of the binary to BCD conversion, for an FPGA it's 6 LUTs (the 6th an input to something following). That likely limits the clock speed to something shy of 100 MHz if the conversion occurs in one clock.
By pipelining or using sequential logic (clocked loop) you'd be able to run an FPGA at it's fastest speed while executing in 6 clocks.
At least two issues appear:
Adding is done after shift, and not before as described in the Double dabble algorithm
The bcd shift goes bcd(11 downto 1), but should be bcd(10 downto 0)
So try with the code:
process ( hex_in )
variable hex_src : std_logic_vector (7 downto 0) ;
variable bcd : std_logic_vector (11 downto 0) ;
begin
hex_src := hex_in ;
bcd := (others => '0') ;
for i in 0 to 7 loop
if bcd(3 downto 0) > "0100" then
bcd(3 downto 0) := bcd(3 downto 0) + "0011" ;
end if ;
if bcd(7 downto 4) > "0100" then
bcd(7 downto 4) := bcd(7 downto 4) + "0011" ;
end if ;
if bcd(11 downto 8) > "0100" then
bcd(11 downto 8) := bcd(11 downto 8) + "0011" ;
end if ;
bcd := bcd(10 downto 0) & hex_src(7) ; -- shift bcd + 1 new entry
hex_src := hex_src(6 downto 0) & '0' ; -- shift src + pad with 0
end loop ;
bcd_hun <= bcd(11 downto 8) ;
bcd_ten <= bcd(7 downto 4) ;
bcd_uni <= bcd(3 downto 0) ;
end process ;
However, the implementation may require a slow clock...
Based on Davids observations in the comments, the code be optimized to:
process ( hex_in )
variable hex_src : std_logic_vector (4 downto 0) ;
variable bcd : std_logic_vector (11 downto 0) ;
begin
bcd := (others => '0') ;
bcd(2 downto 0) := hex_in(7 downto 5) ;
hex_src := hex_in(4 downto 0) ;
for i in hex_src'range loop
if bcd(3 downto 0) > "0100" then
bcd(3 downto 0) := bcd(3 downto 0) + "0011" ;
end if ;
if bcd(7 downto 4) > "0100" then
bcd(7 downto 4) := bcd(7 downto 4) + "0011" ;
end if ;
-- No roll over for hundred digit, since in 0 .. 2
bcd := bcd(10 downto 0) & hex_src(hex_src'left) ; -- shift bcd + 1 new entry
hex_src := hex_src(hex_src'left - 1 downto hex_src'right) & '0' ; -- shift src + pad with 0
end loop ;
bcd_hun <= bcd(11 downto 8) ;
bcd_ten <= bcd(7 downto 4) ;
bcd_uni <= bcd(3 downto 0) ;
end process ;
1.you need take bit 10 to 0 of BCD and from 6 to 0 of hex_src to shift properly.
2.after the 8th shift, the hex_src value you should not add further, try restricting adding
on 7th shifting, you can use if statement to avoid.
after each conversion reset BCD value to zero.
after above correction code should work
This works in quartus 18.1 lite
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
--converting a 8bit binary number to a 12bit bcd
entity bin2bcd is
port (bin :in std_logic_vector (7 downto 0);
bcd1 : out std_logic_vector (3 downto 0);
bcd2 : out std_logic_vector (3 downto 0);
bcd3 : out std_logic_vector (3 downto 0));
end entity;
architecture rtl of bin2bcd is
begin
process ( bin )
variable binx : std_logic_vector (7 downto 0) ;
variable bcd : std_logic_vector (11 downto 0) ;
begin
bcd := (others => '0') ;
binx := bin(7 downto 0) ;
for i in binx'range loop
if bcd(3 downto 0) > "0100" then
bcd(3 downto 0) := std_logic_vector(unsigned( bcd(3 downto 0)) + "0011");
end if ;
if bcd(7 downto 4) > "0100" then
bcd(7 downto 4) := std_logic_vector(unsigned( bcd(7 downto 4)) + "0011");
end if ;
bcd := bcd(10 downto 0) & binx(7) ;
binx := binx(6 downto 0) & '0' ;
end loop ;
bcd3 <= bcd(11 downto 8) ;
bcd2 <= bcd(7 downto 4) ;
bcd1 <= bcd(3 downto 0) ;
end process ;
end architecture;
Can anyone tell if this is the correct code for shift left logical (sll) and shift right logical (srl) on MIPS?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
-- library UNISIM;
-- use UNISIM.VComponents.all;
entity ALU is
port (RdData1 : in std_logic_vector (31 downto 0);
RdData2 : in std_logic_vector (31 downto 0);
FAddr : in std_logic_vector (15 downto 0);
ALUSrc : in std_logic;
ALUOP : in std_logic_vector (2 downto 0); --S-a marit lungimea lui ALUOP
Y : out std_logic_vector (31 downto 0));
end ALU;
architecture Behavioral of ALU is
signal SEAddr : std_logic_vector(31 downto 0);
signal OP2 : std_logic_vector(31 downto 0);
begin
SEAddr(15 downto 0) <= FAddr(15 downto 0);
SEAddr(31 downto 16) <= x"0000" when FAddr(15) = '0' else x"FFFF";
OP2 <= RdData2 when ALUSrc = '0' else SEAddr;
with ALUOP select
Y <= RdData1 + OP2 when "000", --S-a marit lungimea lui ALUOP
RdData1 - OP2 when "001", --S-a marit lungimea lui ALUOP
RdData1 and OP2 when "010", --S-a marit lungimea lui ALUOP
RdData1 or OP2 when "011", --S-a marit lungimea lui ALUOP
RdData1(30 downto 0) & "0" when "100", --sll ,
"0" & RdData1(1 downto 31) when "101", --srl ,
RdData1 when others;
end Behavioral;
I'm adding the controler maybe my misstake is here, i will add a printscreen with my test banch wave for you to understand better why this is not working :
entity ctrl is
Port ( OP : in STD_LOGIC_VECTOR (5 downto 0);
Funct : in STD_LOGIC_VECTOR (5 downto 0);
ALUSrc : out STD_LOGIC;
ALUOP : out STD_LOGIC_VECTOR (2 downto 0);--S-a marit lungimea lui ALUOP
MemWr : out STD_LOGIC;
Mem2Reg : out STD_LOGIC;
RegWr : out STD_LOGIC;
RegDest : out STD_LOGIC);
end ctrl;
architecture Behavioral of ctrl is
signal OPCIntrn : std_logic_vector(6 downto 0);
signal temp : std_logic_vector(7 downto 0);
begin
with OP select
OPCIntrn (6) <= '0' when "000000",
'1' when others;
with OP select
OPCIntrn (5 downto 0) <= Funct when "000000",
OP when others;
with OPCIntrn select
temp <= b"0_000_0_0_1_1" when b"010_0000", --add
b"0_001_0_0_1_1" when b"010_0010", --sub
b"0_010_0_0_1_1" when b"010_0100", --and
b"0_011_0_0_1_1" when b"010_0101", --or
b"1_000_0_1_1_0" when b"110_0011", --lw
b"0_100_0_0_1_1" when b"000_0000", --sll
b"0_101_0_0_1_1" when b"000_0010", --sll
b"1_000_1_0_0_0" when b"110_1011", --sw
b"0_000_0_0_0_0" when others;
RegDest <= temp(0);
RegWr <= temp(1);
Mem2Reg <= temp(2);
MemWr <= temp(3);
ALUOP (2 downto 0) <= temp(6 downto 4);
ALUSrc <= temp(7);
end Behavioral;
In the code above RdData1 is declared as std_logic_vector(31 downto 0) but
for SRL the RdData1 is used as RdData1(1 downto 31). This creates a null
range, which should result in tool warning.
This must be corrected to RdData1(31 downto 1).
The instruction definition for SLL and SRL can be seen here MIPS
architecture.
I'm learning VHDL for programming a FPGA, basic (but hard-for-me) projects. I have this ALU. It is supossed to be a 4-bit ALU. But when I want to make the Add operation the value of result is UUUU. For all other operations is working fine.
Any advise?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU is
Port (
clk: in std_logic;
reset: in std_logic;
operation: in std_logic_vector (2 downto 0)
);
end ALU;
architecture Behavioral of ALU is
signal A : std_logic_vector (3 downto 0) := "0001";
signal B : std_logic_vector (3 downto 0) := "1111";
signal result : std_logic_vector (7 downto 0);
signal flags : std_logic_vector (2 downto 0); -- [S,OF,Z]
begin
process (operation) begin
flags <= (others => '0');
result <= (others => '0');
case operation is
when "000" =>
result <= std_logic_vector((unsigned("0000"&A) + unsigned(B)));
flags(1) <= result(4);
when "001" =>
if (A >= B) then
result <= std_logic_vector(unsigned("0000"&A) - unsigned(B));
flags(2) <= '0';
else
result <= std_logic_vector(unsigned("0000"&B) - unsigned(A));
flags(2) <= '1';
end if;
when "010" =>
result <= "0000"&A and "0000"&B;
when "011" =>
result <= "0000"&A or "0000"&B;
when "100" =>
result <= "0000"&A xor "0000"&B;
when "101" =>
result <= not ("1111"&A);
when "110" =>
result <= not ("1111"&B);
when "111" =>
result <= std_logic_vector(unsigned(A) * unsigned(B));
when others =>
result <= (others => 'Z');
end case;
end process;
end Behavioral;
The only way I can see all Us happening (with the code as is) is if the process never executes. Which means you must have no transactions on the operation signal for the add operation.
Which only raises more questions:
Are you definitely getting Us (not Xs maybe?): is something else driving the signal as well?
Can you post your testbench code?
The first two things that come to mind looking at your code are:
You should include A and B in the process sensitivity list (now it only contains operation).
You can't use result(4) to set flags(1), as result(4) will only be updated after the process, and result itself isn't on the sensitivity list again so the process won't be triggered again to reflect the changed value. The best option is probably to store the sum in a variable, then assign that to result and the overflow bit.