library ieee;
use ieee.std_logic_1164.all;
-- create a entity
entity ex1_3 is
port(
a,b,c,d: in std_logic_vector (3 downto 0);
ctrl: in std_logic;
sum: out std_logic );
end ex1_3;
architecture impl of ex1_3 is
-- declare a component of four bit ripple carry adder
component four_bit_ripple_carry_adder is
port(
a,b: in std_logic_vector (3 downto 0);
cin: in std_logic;
s: out std_logic_vector (3 downto 0);
cout:out std_logic
);
end component;
signal s: std_logic_vector (3 downto 0);
begin
process(a,b,c,d,ctrl)
begin
-- error:Illegal sequential statement.
if ctrl = '0' then
u0: four_bit_ripple_carry_adder port map(a,b,ctrl,s,sum);
elsif ctrl = '1' then
u1: four_bit_ripple_carry_adder port map(c,d,ctrl,s,sum);
end if;
end architecture;
** Error: /home/atomman/drs_exercises/exercise_04/ex1_3.vhd(30): Illegal sequential statement.
** Error: /home/atomman/drs_exercises/exercise_04/ex1_3.vhd(32): Illegal sequential statement.
** Error: /home/atomman/drs_exercises/exercise_04/ex1_3.vhd(35): near "architecture": (vcom-1576) expecting PROCESS.
Never forget that the "H" in HDL stands for "Hardware".
What you are saying is "if ctrl=0 then use a piece of hardware, name it u0 which is connect as ... else replace that piece of hardware, now name it u1 and connect it as ...".
There is no simple hardware equivalent that dynamically, based on a signal (in this case 'ctrl') swaps in and out two components.
The only difference is in the first two ports, which makes the solution simple: You make one component and use a multiplexer1 for the first two input ports:
signal a_or_c_mux: std_logic_vector (3 downto 0);
signal b_or_d_mux: std_logic_vector (3 downto 0);
a_or_c_mux <= a when ctrl='0' else c;
b_or_d_mux <= b when ctrl='0' else d;
Now you can instance your module (once! and outside a process) and use the signals a_or_c_mux and b_or_d_mux as input to the first two ports of the module.
1On purpose I am using 'hardware' nomenclature.
Related
The logic gate in the RTL view was a latch previously. As an answer suggests, I assign each input with outputs. And the latch turns into a logic gate. I don't know whether it is a correct way to solve the problem. There is also an adder connected to the counter.
I want to eliminate the adder and the logic gate. (??? T^T).
What should I modify?
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use IEEE.std_logic_unsigned.all;
entity mux8x1 is port( input: in std_logic_vector( 7 downto 0); clk: in std_logic; --s: buffer std_logic; --rst : in std_logic; --d: buffer std_logic; q: out std_logic_vector (7 downto 0) --o: buffer std_logic_vector (3 downto 0) ); end mux8x1;
architecture mux of mux8x1 is signal count : std_logic_vector(3 downto 0);
--signal count_state: std_logic_vector (3 downto 0); signal serial: std_logic;
--shiftregister
signal internal: std_logic_vector (7 downto 0); signal d: std_logic;
begin --【The counter】 process(clk) --variable internal: std_logic_vector (7 downto 0); --variable d: std_logic; --variable initial: std_logic_vector (7 downto 0) :="01010101";
begin
if (clk'event and clk = '1') then
count <= count + 1;
end if;
end process;
--count_state <= count; --To divide the counter
--section1 for the counter --8x1 multiplxer combined with counter
process(count,input,clk) --variable serialin: std_logic; begin --serialin:='0'; if (count(3) <='0') then case count(2 downto 0) is --8 possible states for PToS
when "000"=> serial <=input(0);
when "001"=> serial <=input(1);
when "010"=> serial <=input(2);
when "011"=> serial <=input(3);
when "100"=> serial <=input(4);
when "101"=> serial <=input(5);
when "110"=> serial <=input(6);
when "111"=> serial <=input(7);
when others => serial <= '0'; end case; else serial <='0';
end if; --serial<=serialin; end process;
-- end if; end mux;
The following is the RTL viewer.
enter image description here
The reason that you get a latch, is because you do not apply a signal value to "serial" in any case when the process is started: Then "serial" keeps its old value which leads to a latch at synthesis, where this kept value is taken from.
So it is a good idea to assign a default value to any signal you assign values to in a process.
When you want to get a register (triggered by a clock edge) you must use a process which is only sensitive to a clock signal (and a reset signal) and uses as a condition "rising_edge(clk)". Of course you do not need a default assignment here.
I'm trying to do a circuit consisting of a 2 to 1 multiplexer (8-bit buses), an 8-bit register and an 8-bit adder. These components are all tested and work as expected.
The thing is: if I try to send the output of the Adder to one of the inputs of the
multiplexer (as seen in the image by the discontinued line), the simulation will stop rather suddenly. If I don't do that and just let ain do its thing, everything will run just as it should, but I do need the output of the adder to be the one inputted to the multiplexer.
The simulation is the following:
The code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sumitas is
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end Sumitas;
architecture rtl of Sumitas is
component Adder8bit
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end component;
component GenericReg
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
component GenericMux2_1
generic (DataWidth : integer := 8);
port (a, b : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
Z : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
constant DW : integer := 8;
signal AddOut_s, MuxOut_s : STD_LOGIC_VECTOR (7 downto 0);
signal PCOut_s : STD_LOGIC_VECTOR (7 downto 0);
begin
m0 : GenericMux2_1
generic map (DataWidth => DW)
port map (a => "00000000",
b => AddOut_s,
Z => m,
S => MuxOut_s);
PC : GenericReg
generic map (DataWidth => DW)
port map (en => clk,
dataIn => MuxOut_s,
dataOut => PCOut_s);
Add0 : Adder8bit
port map (a => "00000001",
b => PCOut_s,
Cin => '0',
S => AddOut_s,
Cout => open);
Add <= AddOut_s;
end rtl;
and the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity bm_Sumitas is
end bm_Sumitas;
architecture benchmark of bm_Sumitas is
component Sumitas
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end component;
signal clk_s, m_s : STD_LOGIC;
signal Add_s, ain_s : STD_LOGIC_VECTOR (7 downto 0);
constant T : time := 2 ns;
begin
benchmark : Sumitas
port map (m => m_s,
clk => clk_s,
ain => ain_s,
Add => Add_s);
clk_proc: process
begin
clk_s <= '0';
wait for T/2;
clk_s <= '1';
wait for T/2;
end process;
bm_proc : process
begin
m_s <= '0';
wait for 10 ns;
m_s <= '1';
wait for 100 ns;
end process;
ains_proc : process
begin
ain_s <= "00001111";
for I in 0 to 250 loop
ain_s <= STD_LOGIC_VECTOR(TO_UNSIGNED(I, ain_s'length));
wait for T;
end loop;
end process;
end benchmark;
How can I do the thing I want? I'm ultimately trying to simulate a computer I designed. I have every component already designed and I'm coupling them together.
Constructing a Minimal, Complete, and Verifiable example requires filling in the missing components:
library ieee;
use ieee.std_logic_1164.all;
entity Adder8bit is
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end entity;
architecture foo of adder8bit is
signal sum: std_logic_vector (9 downto 0);
use ieee.numeric_std.all;
begin
sum <= std_logic_vector ( unsigned ('0' & a & cin) +
unsigned ('0' & b & cin ));
s <= sum(8 downto 1);
cout <= sum(9);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity GenericReg is
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end entity;
architecture fum of genericreg is
begin
dataout <= datain when en = '1';
end architecture;
with behavioral model substitutes.
(It's not that much work, copy the component declarations paste them, substitute entity for component and add the reserved word is, followed by simple behaviors in architectures.)
It reproduces the symptom you displayed in your simulation waveform:
You can see the essential point of failure occurs when the register enable (ms_s) goes high.
The simulator will report operation on it's STD_OUTPUT:
%: make wave
/usr/local/bin/ghdl -a bm_sumitas.vhdl
/usr/local/bin/ghdl -e bm_sumitas
/usr/local/bin/ghdl -r bm_sumitas --wave=bm_sumitas.ghw --stop-time=40ns
./bm_sumitas:info: simulation stopped #11ns by --stop-delta=5000
/usr/bin/open bm_sumitas.gtkw
%:
Note the simulation stopped at 11 ns because of a process executing repeatedly in delta cycles (simulation time doesn't advance).
This is caused by a gated relaxation oscillator formed by the enabled latch, delay (a delta cycle) and having at least one element of latch input inverting each delta cycle.
The particular simulator used has a delta cycle limitation, which will quit simulation when 5,000 delta cycles occur without simulation time advancing.
The genericreg kept generating events with no time delay in assignment, without an after clause in the waveform, after 0 fs (resolution limit) is assumed.
Essentially when the enable is true the signal will have at least one element change every simulation cycle due to the increment, and assigns the signal a new value for at least one element each simulation cycle without allowing the advancement of simulation time by not going quiescent.
You could note the simulator you used should have produced a 'console' output with a similar message if it were capable (and enabled).
So how it this problem cured? The easiest way is to use a register (not latch) sensitive to a clock edge:
architecture foo of genericreg is
begin
dataout <= datain when rising_edge(en);
end architecture;
Which gives us the full simulation:
I get this error:
# Error: COMP96_0100: data_reg.vhd : (156, 35): Actual parameter type in port map does not match the port formal type "Allin".
# Error: COMP96_0100: data_reg.vhd : (158, 1): Actual parameter type in port map does not match the port formal type "Fout".
# Error: COMP96_0100: data_reg.vhd : (162, 1): Actual parameter type in port map does not match the port formal type "D".
# Error: COMP96_0100: data_reg.vhd : (163, 1): Actual parameter type in port map does not match the port formal type "Q".
I need some help, please.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ticket1 is
port (
A, B : in std_logic_vector(7 downto 0);
Clock: in std_logic;
O: out std_logic_vector(7 downto 0));
end entity;
architecture Ticketmachine of ticket1 is
component ticket_selection
port(
Allin:in bit_vector(3 downto 0);
Clk: in std_logic;
Fout: out bit_vector(7 downto 0));
end component ticket_selection;
component reg is
port(
C: in std_logic;
D: in bit_vector(7 downto 0);
Q : out bit_vector(7 downto 0));
end component reg;
component Money is
port (
Ai,Bi : in std_logic_vector(7 downto 0);
Fo: out std_logic_vector(7 downto 0));
end component money;
signal s1,s2: std_logic_vector(7 downto 0);
begin
Option: ticket_selection
port map(
Allin=>A,
Clk=>Clock,
Fout=>s1);
Cash: reg
port map(
C=>Clock,
D=>B,
Q=>s2);
Pros: Money
port map(
Ai=>s1,
Bi=>s2,
Fo=>O);
end architecture;
You should read carefully some VHDL guide for beginners. I can't recommend any (maybe someone could?), so I'll go straight to your mistakes here:
Never use std_logic_unsigned, std_logic_unsigned, and std_logic_arith. This libraries are not part of standard, and can be replaced with numeric_std.
Don't use bit or bit_vector type. Use std_logic, and std_logic_vector instead.
When you associate one vector to other, they must have equal type and length, as user1155120 and Brian Drummond wrote in comment. In particular, you can't assign std_logic_vector(7 downto 0) to bit_vector(3 downto 0).
There are probably more things done wrong here, but your question is not complete - you didn't provide any explanation what it should do, no full code, and no testbench.
I am trying to program an FPU unit in VHDL. I am doing my first steps. I get two errors while executing this instruction:
mantissa1 <= std_logic_vector(resize(unsigned(mantissa1),mantissa1'length + d));
The errors are:
Error: C:/Modeltech_pe_edu_10.4a/examples/fpu/shifter.vhd(38): Illegal type conversion to ieee.std_logic_1164.STD_LOGIC_VECTOR (operand type is not known).
Error: C:/Modeltech_pe_edu_10.4a/examples/fpu/shifter.vhd(36): (vcom-1078) Identifier "unsigned" is not directly visible.
Here is my code
library ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_misc.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_arith.ALL;
use ieee.numeric_std.all;
entity fpu is
port (
E1,E2 : IN std_logic_vector( 30 downto 23);
M1,M2 : IN std_logic_vector( 22 downto 0);
S1,S2 : IN std_logic_vector (31 downto 31);
op : IN std_logic_vector (1 downto 0);
SUM : OUT std_logic_vector (45 downto 0);
E : OUT std_logic_vector (7 downto 0);
clk : IN std_logic
);
end entity;
architecture arch_fpu of fpu is
SIGNAL d: integer;
SIGNAL mantissa1 : std_logic_vector (22 DOWNTO 0) ;
SIGNAL mantissa2 : std_logic_vector (22 DOWNTO 0) ;
begin
process(E1,E2,M1,M2,S1,S2,clk)
BEGIN
if((op="01") or (op="00")) then
E<=E1 when E1>E2 else
E2;
d<=abs(conv_integer(E1-E2));
mantissa1 <= std_logic_vector(resize(unsigned(mantissa1),mantissa1'length + d));
end if;
END process;
end arch_fpu;
You are mixing VHDL math libraries. I suggest you use either numeric_std (my preference) or std_logic_unsigned/std_logic_arith, but not both.
There are several other issues as well. You cannot assign the larger (by 'd' bits) manitissa1 value back to manitissa1, you need a target of the appropriate size. Your subtraction of E1-E2 will need some type conversion to be legal, perhaps: signed(E1) - signed(E2)
Honestly, you probably want to rethink the whole approach to what you are trying to do, especially if you expect to synthesize this code into logic.
I am trying to add two std_logic_vectors using the notation given below:-
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--use IEEE.NUMERIC_STD.ALL;
entity adder is
port( a:in std_logic_vector(31 downto 0);
b:in std_logic_vector(31 downto 0);
o:out std_logic_vector(31 downto 0));
end adder;
architecture Behavioral of adder is
begin
o<=a+b;
end Behavioral;
One possibility is to generate the result with carry, and then split that afterwards, like:
architecture Behavioral of adder is
signal c_o : std_logic_vector(o'length downto 0); -- Result with carry
signal c : std_logic; -- Carry only
begin
c_o <= ('0' & a) + b; -- Result with carry; extended with '0' to keep carry
o <= c_o(o'range); -- Result without carry
c <= c_o(c_o'left); -- Carry only
end Behavioral;
You can do this. The carry is not saved, but it's being reported that there was an overflow.
function "+" (Add1: std_logic_vector; Add2: std_logic_vector) return std_logic_vector is
variable big_sum: bit_vector(Add1'LENGTH downto 0);
begin
big_sum = Add1 + Add2;
assert big_sum(Add1'LENGTH) = 0
report "overflow"
severity warning;
return big_sum(Add1'LENGTH-1 downto 0);
Of course you'll need to define a new package and also include that package in your already existing file.
o<=std_logic_vector(unsigned(a)+unsigned(b))
Although I suggest you use unsigned/signed on your ports (and have a clock cycle of latency).
If you want the carry
o_with_carry <= std_logic_vector('0'&unsigned(a)+unsigned(b));
o_carry <= o_with_carry(o_with_carry'high);
o <= o_with_carry(o'range);