FSM for 4-bit UP-counter on VHDL - vhdl

Hay, I've coded my 4-bit up counter already but I need some help with this certain part.
The up counter works fine but I need to make some changes to my input so it follows my lab requirement.
Design a 4-bit UP-counter which counts from 0 through n and follows the sequence
[0, n^0+a, n^1+a, n^2+a, n^3+a, ....].
I'm suppose to use two input vectors of n and a and they both are 2-bits each. My clock suppose to be connected into SW0, also, I'm suppose to connect n to SW1-SW2 and a to SW3-SW4.
I've already connected everything I just need help and understanding on how can I implement a and n in the following code.
As the instructions says I can not use Multipliers or Adders.
Any help would be appreciated.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity upCounter is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
--n : in STD_LOGIC_VECTOR (1 downto 0);
--a : in STD_LOGIC_VECTOR (1 downto 0);
output : out STD_LOGIC_VECTOR (3 downto 0)
);
end upCounter;
architecture Behavioral of upCounter is
signal count: STD_LOGIC_VECTOR (3 downto 0);
begin
process (clk, reset)
begin
if reset = '1' then
count <= "0000";
elsif clk'event and clk = '1' then
count <= count + 1;
end if;
end process;
output <= count;
end Behavioral;

Related

How to eliminate the logic gate and the adder

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.

Vivado stops simulation on feedback circuit

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:

Weird behaviour in vhdl average using Microsemi FPGA

Good Afternoon, I am working on some code of averaging with a sliding window using VHDL language.
The problem is that the accumulator takes sometimes wrong values. (generally after restart)
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.std_logic_unsigned.all;
entity cc_rssi_avr is
port (
nrst : in std_logic;
clk : in std_logic; --
ena : in std_logic;
data_in : in std_logic_vector(9 downto 0);
data_out : out std_logic_vector(9 downto 0)
);
end cc_rssi_avr;
architecture rtl of cc_rssi_avr is
constant buffer_size : natural :=8;
type MEM is array(0 to buffer_size-1) of std_logic_vector(9 downto 0);
signal shift_LT : MEM:=(others =>(others=>'0'));
signal sum_val:std_logic_vector(12 downto 0);
begin
--shift input data at every clock edge
process(clk,nrst)
begin
if nrst='0' then
shift_LT <= (others => (others => '0'));
sum_val <= (others=>'0');
elsif clk'event and clk='1' then
if ena = '0' then
shift_LT<=(others=>(others=>'0'));
sum_val<=(others=>'0');
else
shift_LT(0) <= data_in;
shift_LT(1 to buffer_size-1) <= shift_LT(0 to buffer_size-2);
sum_val <= sum_val + ("000"&data_in) - ("000"&shift_LT(buffer_size-1));
end if;
end if;
end process;
data_out<=sum_val(sum_val'high downto 3);
end rtl;
The problem is somehow, sum_val adds a value without subtraction or subtracts without addition, in a way that if the input returns to 0, the output returns to 7850 or a random value but not zero.
The design is running # 20 MHz (FPGA : Microsemi Smartfusion M2S050), and consists on an ADC driven by FPGA clock, and its output is routed to the FPGA pins so the samples are processed with this module in order to compute the average on 8 samples.
One last information that might be useful : FPGA is 92.6% Occupied (4LUT).
Can anyone provide some help.
Thanks

Implementing Overflow Checking in 4-bit Adder/Subtractor (VHDL)

I am rather new (3 weeks) to VHDL, and I am having a problem in my latest assignment, which involves implementing overflow checking in a simple 4-bit adder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity add_sub_4bit is
Port ( a : in STD_LOGIC_VECTOR(3 downto 0);
b : inout STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC );
--sum : inout STD_LOGIC_VECTOR(3 downto 0)
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal localsum : STD_LOGIC_VECTOR (3 downto 0);
begin
localsum <= a + b when sel = '1'
else
a - b;
process(a,b,localsum) begin
if a(3) = '0' AND b(3) = '0' AND localsum(3) = '1' then
localflow <= '1';
elsif a(3) = '1' AND b(3) = '1' AND localsum(3) = '0' then
localflow <='1';
else
localflow <='0';
end if;
end process;
end Behavioral;
Now, the test cases are as such:
A=5, B=-3, giving 0 to sel adds them, 1 subtracts.
A=6, B=2, working much the same.
Now, given that the numbers are signed, of course, they are two's complement numbers, so is the result. However, I can only detect overflow in a case of adding 6 (0110) and 2 (0010), giving out -8 (1000), which is obviously an overflow case in 4-bit. But, when doing 5 -(-3), the result is much the same, 1000, but since I have given numbers of two different signs, I cannot detect overflow using my method.
My teacher has suggested that we change the sign of B depending on the value of sel - I tried something like making b <= b+"1000" based on that but that didn't help, and I don't know of other ways, being very new to the language. What can I do to get a proper program? Thank you.
Firstly:
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Don't do that. Especially if you want the numbers to be signed. Normal to use is:
use IEEE.numeric_std.all;
After that, you should cast the std_logic_vector to the wanted data type, e.g. 'signed', for the correct arithmetic.
Secondly, don't use inout. VHDL is not so good with bidirectional assignments. Either use in or out.
So combining the above, you could do (n.b. not the best code):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit is
Port (
a : in STD_LOGIC_VECTOR(3 downto 0);
b : in STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(3 downto 0);
overflow : out std_logic
);
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal locala, localb, localsum : signed(4 downto 0); -- one bit more then input
signal sumout : std_logic_vector(4 downto 0);
begin
locala <= resize(signed(a), 5);
localb <= resize(signed(b), 5);
localsum <= locala + localb when sel = '1' else locala - localb;
-- overflow occurs when bit 3 is not equal to the sign bit(4)
localflow <= '1' when localsum(3) /= localsum(4) else '0';
-- convert outputs
sumout <= std_logic_vector(localsum);
--outputs
sum <= sumout(4)&sumout(2 downto 0);
overflow <= localflow;
end Behavioral;
You can test this using a testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit_tb is
end add_sub_4bit_tb;
architecture Behavioral of add_sub_4bit_tb is
signal sel : std_logic_vector(0 downto 0);
signal a, b, sum : std_logic_vector(3 downto 0);
begin
uut: entity work.add_sub_4bit
port map (a, b, sel(0), sum);
test: process
begin
for sel_o in 0 to 1 loop
sel <= std_logic_vector(to_signed(sel_o, 1));
for a_o in -8 to 7 loop
a <= std_logic_vector(to_signed(a_o, 4));
for b_o in -8 to 7 loop
b <= std_logic_vector(to_signed(b_o, 4));
wait for 1 ns;
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;

Counting down from an input value in VHDL

I'm trying to assign the value of input aa to the signal t in the code below. It compiles successfully, but there is a warning:
WARNING[9]: C:/Modeltech_5.7f/examples/hassan1.vhd(14): (vcom-1013) Initial value of "t" depends on value of signal "aa".
Here is the code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all ;
use ieee.numeric_std.all;
entity counter is
port(clk :in std_logic;
reset : in std_logic;
aa: in std_logic_vector(3 downto 0);
check : out std_logic_vector(3 downto 0));
end counter;
architecture imp of counter is
signal i:std_logic_vector(3 downto 0):="0000";
signal t:std_logic_vector(3 downto 0):=aa;
begin
process(clk)
begin
if rising_edge(clk) and (t>0) then
t<=t-1;
i<=i+1;
end if;
end process;
check<=i;
end imp;
What should I be doing in order to decrement the input 'aa' in the process? The program is meant to decrement the value at input aa to 0.
It looks like you are trying to implement a down-counter with a load input. In such a counter, when load_enable = '1' you should register the load input value (aa in your case) into an internal signal. When load_enable = '0', you would decrement this count value. Here is a code example that does that:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity down_counter is
port (
clock: in std_logic;
reset: in std_logic;
load_enable: in std_logic;
load_data: in std_logic_vector(3 downto 0);
output: out std_logic_vector(3 downto 0)
);
end;
architecture rtl of down_counter is
signal count: std_logic_vector(3 downto 0);
begin
process (clock, reset) begin
if reset then
count <= (others => '0');
elsif rising_edge(clock) then
if load_enable then
count <= load_data;
else
count <= count - 1;
end if;
end if;
end process;
output <= count;
end;
For the record, the code above can be improved, but I didn't want to throw too much stuff at once. It is probably a good idea to use an integer instead of std_logic_vector for your count signal. Also you should check if the count proceeds as you expected, since the example uses the numeric_std_unsigned package. I'd recommend that you change it to numeric_std once you understand the code completely.

Resources