how to increment 5 bit numbers in vhdl - vhdl

I am working on implementing a counter component to my vending machine where a user can select 2 items candy 5 cent gum is 10 cent and came across some difficulties with how do I increment a number by 5 or 10 depending on what the user select when I run my code I am getting a runtime error when trying to simulate it also the user can only put up to 30 cent into the machine.
the counter component only keeps track of the amount of nickels or dimes put into the machine such as: 5 cent then another 10 cent the counter will increment to 15
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity count is port(clk,reset,nickel,dime:in std_logic;
totalAmt:out std_logic_vector(3 downto 0));
end count;
architecture beh of count is
signal sum:std_logic_vector(3 downto 0);
signal tmp1: std_logic_vector(3 downto 0) := "0101";
signal tmp2: std_logic_vector(3 downto 0) := "1010";
signal tally: std_logic_vector(3 downto 0);
signal grantot: std_logic_vector(3 downto 0);
begin
process(clk,reset,nickel,dime,sum)
begin
sum <= "0000";
tally <= "0000";
if (reset = '1') then sum <= "0000";
elsif(clk'event and clk = '1') then
elsif(nickel = '1') then sum <= tmp1; -- when nickel or dime is set to one it increments the sume amount by 5 or 10 in binary
elsif(dime = '1') then tally <= tmp2;
end if;
end process;
grantot <= sum + tally;
--if sum >= "11110" then
--report "error";
--else
totalAmt <= grantot;
--end if;
end;

You can't do the math directly on STD_LOGIC_VECTOR signals. You need to declare some sort of math type - I would recommend the type UNSIGNED, which is included in the IEEE.NUMERIC_STD.ALL package that you already include in your code.
You can declare it as follows:
signal sum : UNSIGNED(4 downto 0) := to_unsigned(<your_number>, <signal_width>;
Where <signal_width> would be 5, since you're using 5 bit numbers.
Keep in mind that you'll need to resize your signals after an addition, since the result of an addition of two numbers is wider than the original operands. You do that as follows:
sum <= resize( tmp1 + tmp2, <signal_width>)
Where <signal_width> will be 5, as that's how wide you declared sum. If you don't do the resize, you will likely get an error saying that your target signal isn't wide enough.

Related

8 bit serial to parallel shifter in vhdl

I programmed an 8-bit shifter in vhdl:
entity 8b is
port(s, clk : in std_logic; p : out std_logic_vector (7 downto 0));
end entity;
architecture arch of 8b is
Signal iq : std_logic_vector (7 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
iq(7) <= s;
iq(6 downto 0) <= iq(7 downto 1);
end if;
end process;
p <= iq;
end architecture;
The idea is that I'm taking input and giving it to my first D-FF.
Then over the next 7 cycles, the other Flip Flops get the other serial inputs which will be given to the parallel output p.
However, I'm not sure if this logic is flawed because this is the solution we got for this exercise:
architecture behavior of 8b is
signal p_intern : std_logic_vector(7 downto 0);
begin
P <= p_intern;
process(CLK)
begin
if rising_edge(CLK) then
p_intern <= p_intern(6 downto 0) & S;
end if;
end process;
end architecture;
But I don't get the p_intern <= p_inter(6 downto 0) & S; part.
Can someone please explain the logic behind this and if my version is also valid?
The only difference between the two implementations seem to be the lines
iq(7) <= s;
iq(6 downto 0) <= iq(7 downto 1);
vs.
p_intern <= p_intern(6 downto 0) & S;
and that iq is named p_intern. Let's assume they are both named iq for the sake of comparison.
Let's see what they are doing:
The first implementation (yours) assigns to the positions of iq:
7 6 5 ... 1 0
s iq(7) iq(6) ... iq(2) iq(1)
The second implementation (the solution) assigns
7 6 5 ... 1 0
iq(6) iq(5) iq(4) ... iq(0) s
Where iq(6 downto 0) & s means "concatenate s to the right of iq(6 downto 0)".
So they are not equivalent. Your implementation shifts in the values from the left, and the solution shifts in the values from the right. Which one is correct depends on the specification (presumably the solution is correct).

VHDL Clock problem while creating modulo 16 counter

I've created this simple mod16 counter using basys3 board and something is not right with my clock. The code itself do works, however one count (changing from "1" to "2" etc.) last 40 seconds, instead of 1 second! I've tried to lower the "clk_vector" if condition to 1 but it didn't help either.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mod_16_k is
Port ( switch : in STD_LOGIC_VECTOR (3 downto 0);
CLK1 : in STD_LOGIC;
reset : in STD_LOGIC;
led : out STD_LOGIC_VECTOR (15 downto 0));
end mod_16_k;
architecture Behavioral of mod_16_k is
signal clk_vector :integer;
signal clk_vec2 :std_logic_vector(15 downto 0);
begin
zegar_wew : process(CLK1)
begin
if(CLK1'event and CLK1 = '1') then
clk_vector <= clk_vector + 1;
if(clk_vector = 100000000) then
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
end if;
end if;
end process;
led <= clk_vec2;
end Behavioral;
The .XDC lines for clock are:
If we check the basys3 datasheet, the clock is connected to "W5" port.
Do you have any idea, what might be the problem in here? It might be connected with detecting the rising edge of an clk, however all of the changes (from 1 to 2 etc.) last ~40 seconds.
This is because you forget to reset clk_vector once it reaches 1 second. Because it is an integer, it is 32 bits, thus will count 2^32 instead of 100000000.
This should work:
If(CLK1'event and CLK1 = '1') then
if(clk_vector = 100000000-1) then
clk_vector <= 0;
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
else
clk_vector <= clk_vector + 1;
end if;
end if;
Also, notice that to count 1 second, you need to count up to 100000000-1, we start counting from zero!

Width mismatch: Variable in vector range for signal assignment. why and how to fix?

ISE 14.7 at synthesis returns the following warning on the subsequent line which eventually leads to an error:
"Width mismatch. <temp> has a width of 8 bits but assigned expression is 128-bit wide."
temp <= padding_start_s((((i_pad+1)*8)-1) downto (i_pad*8));
The problem seems to be with the for loop. What I am trying to do is to pad an incoming signal of N multiples of 128 bit. Eventually a non-complete 128 bit signal is received and I want to detect where it eventually ends and then add padding. Certainly, some of the code is missing, but this should really be the relevant stuff.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.NUMERIC_STD.all;
library work;
use work.keccak_globals.all;
entity Keccak_padder is
port (
clk_i : in std_logic;
data_i : in std_logic_vector(127 downto 0);
rst_n : in std_logic;
start_i : in std_logic;
end_i : in std_logic;
state_vector_o : out std_logic_vector(r-1 downto 0);
state_vector_valid_o : out std_logic;
long_message_o : out std_logic
);
end Keccak_padder;
architecture Behavioral of Keccak_padder is
signal word_count : integer range 1 to 16:=1;
signal pad_count : integer range 0 to 3:=0;
signal i_pad : integer range 0 to 15;
signal word_count : integer range 1 to 16:=1;
signal padding_start_s : std_logic_vector(127 downto 0):=(others=>'0');
signal temp : std_logic_vector(7 downto 0);
constant zero_vector : std_logic_vector(7 downto 0):=(others=>'0');
signal start_pad : std_logic;
process(clk_i, rst_n, fsm_state, pad_count, start_pad, padding_start_s)
begin
if rising_edge(clk_i) then
case fsm_state is
when IDLE =>
...
when TRANSMIT =>
...
when RECEIVE =>
if (pad_count = 1) then
state_vector_o((r-1-(data_i'length * (word_count - 1))) downto (r-(data_i'length * (word_count)))) <= temp;
pad_count <= 0;
fsm_state <= IDLE;
start_pad <= '0';
elsif (start_pad = '1') then
temp <= padding_start_s((((i_pad+1)*8)-1) downto (i_pad*8));
pad_count <= pad_count + 1;
end if;
for i in 15 downto 0 loop
if (padding_start_s((((i+1)*8)-1) downto ((i)*8)) = zero_vector) then
i_pad <= i;
start_pad <= '1';
exit;
end if;
end loop;
end case;
end if;
end process;
So eventually what I'm asking is: how do I find a way around this and why is this a problem? Is it wrong to be cutting the range in a signal assignment?
Thanks!
Without a Minimal, Complete, and Verifiable example an answer is hit or miss, and this is a synthesis issue instead of VHDL language syntax or semantic issue.
As Brian commented the temp assignment is a 16:1 mux for an 8 bit wide value, it's possible to simplify the indexing. Even more than Brian suggests:
type byte_array_16 is array (15 downto 0) of std_logic_vector (7 downto 0);
signal padding_bytes: byte_array_16;
begin
padding_bytes <= byte_array_16'(
padding_start_s(127 downto 120), padding_start_s(119 downto 112),
padding_start_s(111 downto 104), padding_start_s(103 downto 96),
padding_start_s( 95 downto 88), padding_start_s( 87 downto 80),
padding_start_s( 79 downto 72), padding_start_s( 71 downto 64),
padding_start_s( 63 downto 56), padding_start_s( 55 downto 48),
padding_start_s( 47 downto 40), padding_start_s( 39 downto 32),
padding_start_s( 31 downto 24), padding_start_s( 23 downto 16),
padding_start_s( 15 downto 8), padding_start_s( 7 downto 0)
);
TEST1: -- temp assignment expression
process
variable i_pad: integer range 0 to 15; -- overloads signal i_pad
begin
for i in 0 to 15 loop
i_pad := i;
-- temp <= padding_start_s((((i_pad + 1) * 8) - 1) downto (i_pad * 8));
temp <= padding_bytes(i_pad);
wait for 0 ns; -- temp assignment takes effect next delta cycle
end loop;
report "Test 1, temp assignment, no bounds errors";
wait;
end process;
The assignment to padding_bytes works as like a union in C, except that it's only goes one way. It also adds no hardware burden.
So the i_pad value determination is a priority encoder from a particular end with a bunch of byte recognizers comparing values to constant zero_vector. Those 16 recognizers (the for loop will get unwound in synthesis) get optimized to just look for all '0's.
What you have besides recognizers is a 16 to 4 priority encoder producing i_pad and start_pad, used to specify any recognizers found all '0's.
But what's hairy is there's all this arithmetic in what you select for inputs to the recognizers. You can fix that with the same one way union:
FIND_FIRST_ZERO_BYTE:
process
begin
start_pad <= '0';
for i in 15 downto 0 loop
if padding_bytes(i) = zero_vector then
i_pad <= i;
start_pad <= '1';
exit;
end if;
end loop;
wait;
end process;
And that eliminates a whole heck of a lot of arithmetic required because i_pad is a signal.

"This port will be preserved and left unconnected if it belongs to a top-level block...." in VHDL

I am getting the following warning in Xilinx when I synthesize my code of a 4-bit multiplier:
"This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved." I dont see any problem in my code that can cause this warning.
The code is as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_bit.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mult4X4 is
Port ( Clk : in bit;
St : in bit;
Mplier : in unsigned (3 downto 0);
Mcand : in unsigned (3 downto 0);
Result : out unsigned (7 downto 0);
Done : out bit);
end mult4X4;
architecture behave1 of mult4X4 is
signal State : integer range 0 to 9;
signal ACC : unsigned (8 downto 0);
alias M : bit is ACC(0);
begin
process(Clk)
begin
if Clk'event and Clk = '1' then
case State is
when 0 =>
if St = '1' then
ACC(8 downto 4) <= "00000";
ACC(3 downto 0) <= Mplier;
State <= 1;
end if;
when 1 | 3 | 5 | 7 =>
if M = '1' then
ACC(7 downto 4) <= ACC(7 downto 4) + Mcand;
ACC(8 downto 0) <= '0' & ACC(8 downto 1);
State <= State + 1;
else
ACC <= '0' & ACC(8 downto 1);
State <= State + 2;
end if;
when 2 | 4 | 6 | 8 =>
ACC <= '0' & ACC(8 downto 1);
State <= State + 1;
when 9 =>
Done <= '1';
State <= 0;
Result <= ACC(7 downto 0);
end case;
end if;
end process;
--Done <= '1' when State = 9 else '0';
--Result <= ACC(7 downto 0);
end behave1;
Notice that the warning is speaking of a port. I expect the line just above would tell you precisely which port, but it's easy enough to derive.
The port will be left unconnected. That means it must have no effect. The easiest way to have no effect is to be unused. All of the ports are accounted for in the process, so we look for other ways they aren't meaningful. Done looks like a prime candidate; it is set to 1 when the state machine finishes, but there's no reset; this means it goes from undefined to high, and stays. The optimizer could replace that with just a high output. A reasonable place to reset it would be at the start condition.
In general the code has no reset, which may be fine if the state machine can recover from any state, but won't simulate properly. Don't be sure it will reset just because of the range of the State signal; having ten values, it would require 4 bits to store causing 6 invisible states with undefined behaviour; or it could well be encoded to one hot, which if not reset could cause multiple states to appear simultaneously.
Try simulating it.
Without simulating it myself I'd guess you're getting all '0's on Result.
These:
ACC(7 downto 4) <= ACC(7 downto 4) + Mcand;
ACC(8 downto 0) <= '0' & ACC(8 downto 1);
Will result in the Multiplicand's influence being eradicated. There is no time between assignments to ACC. See IEEE Std 1076-1993 8.4.1 Updating a projected output waveform (-2008 10.5.2.2 Executing a simple assignment statement), the paragraph starting "The sequence of transactions is ..." and the following narrative. The first assignment's scheduled transaction for the affected bits of ACC (7 downto 4) are deleted as old transactions. For composite types (and ACC is) it happens on an element by element basis.
And it looks like it will get all '0's because of the second assignment statement.
Also from simply reading your state machine the second of those two ACC assignments should simply be deleted in States 1 | 3 | 5 | 7?
Addendum
After Yann Verneir pointed out another error with Done never being assigned '0' I figured I'd demonstrate the effects of the two assignment statements to ACC in States 1 | 3 | 5 | 7.
A simple testbench:
library ieee;
use ieee.numeric_bit.all;
entity mult4x4_tb is
end entity;
architecture foo of mult4x4_tb is
signal clk: bit;
signal start: bit;
signal multiplier: unsigned (3 downto 0) := X"2";
signal multiplicand: unsigned (3 downto 0) := X"4";
signal result: unsigned (7 downto 0);
signal done: bit;
begin
DUT:
entity work. mult4x4
port map (
Clk => clk,
St => start,
Mplier => multiplier,
Mcand => multiplicand,
Result => result,
Done => done
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 300 ns then
wait;
end if;
end process;
STIM:
process
begin
wait for 29 ns;
start <= '1';
wait for 20 ns;
start <= '0';
wait;
end process;
end architecture;
gives:
You can see that when using package numeric_bit instead of packages std_logic_1164 and numeric_std we never see anything but all '0's on Result.
Yann's assignment to '1' only on Done can be cured by:
case State is
when 0 =>
if St = '1' then
ACC(8 downto 4) <= "00000";
ACC(3 downto 0) <= Mplier;
State <= 1;
Done <= '0';
end if;
Removing the second signal assignment to ACC in the sequential statements for cases 1 | 3 | 5 | 7 gives an answer that look's right for 2 x 4:

VHDL How to convert 32 bit variable to 4 x 8bit std_logic_vector?

I have a question which is probably in 2 parts:
I am using a (nominally 32 bit) integer variable which I would like to write to an 8 bit UART as 4 bytes (i.e., as binary data)
i.e. variable Count : integer range 0 to 2147483647;
How should I chop the 32 bit integer variable into 4 separate 8 bit std_logic_vectors as expected by my UART code, and how should I pass these to the UART one byte at a time ?
I am aware std_logic_vector(to_unsigned(Count, 32)) will convert the integer variable into a 32 bit std_logic_vector, but then what ? Should I create a 32 bit std_logic_vector, assign the converted Count value to it, then subdivide it using something like the following code ? I realise the following assumes the count variable does not change during the 4 clock cycles, and assumes the UART can accept a new byte every clock cycle, and lacks any means of re-triggering the 4 byte transmit cycle, but am I on the right track here, or is there a better way ?
variable CountOut : std_logic_vector(31 downto 0);
process (clock)
variable Index : integer range 0 to 4 := 0;
begin
if rising_edge(clock) then
CountOut <= std_logic_vector(to_unsigned(Count, 32);
if (Index = 0) then
UartData(7 downto 0) <= CountOut(31 downto 24);
Index := 1;
elsif (Index = 1) then
UartData(7 downto 0) <= CountOut(23 downto 16);
Index := 2;
elsif (Index = 2) then
UartData(7 downto 0) <= CountOut(15 downto 8);
Index := 3;
elsif (Index =31) then
UartData(7 downto 0) <= CountOut(7 downto 0);
Index := 4;
else
Index := Index;
end if;
end if;
end process;
Any comments or recommendations would be appreciated.
Thanks,
MAI-AU.
You seem to be on the right track. I believe there are two basic solutions to this problem:
Register the output value as a 32-bit vector, and use different ranges for each output operation (as you did in your code example)
Register the output value as a 32-bit vector, and shift this value 8 bits at a time after each output operation. This way you can use the same range in all operations. The code below should give you an idea:
process (clock)
variable Index: integer range 0 to 4 := 0;
begin
if rising_edge(clock) then
if (Index = 0) then
CountOut <= std_logic_vector(to_unsigned(Count, 32));
Index := Index + 1;
elsif (Index < 4) then
UartData <= CountOut(31 downto 24);
CountOut <= CountOut sll 8;
Index := Index + 1;
end if;
end if;
end process;
Also, please check your assignments, in your example CountOut is declared as a variable but is assigned to as a signal.
There's nothing wrong with the code you've shown. You can do something to separate the the assignment to UartData using Index to allow a loop.
library ieee;
use ieee.std_logic_1164.all;
entity union is
end entity;
architecture foo of union is
type union32 is array (integer range 1 to 4) of std_logic_vector(7 downto 0);
signal UartData: std_logic_vector(7 downto 0);
begin
TEST:
process
variable quad: union32;
constant fourbytes: std_logic_vector(31 downto 0) := X"deadbeef";
begin
quad := union32'(fourbytes(31 downto 24), fourbytes(23 downto 16),
fourbytes(15 downto 8),fourbytes(7 downto 0));
for i in union32'RANGE loop
wait for 9.6 us;
UartData <= Quad(i);
end loop;
wait for 9.6 us; -- to display the last byte
wait; -- one ping only
end process;
end architecture;
Or use a type conversion function to hide complexity:
library ieee;
use ieee.std_logic_1164.all;
entity union is
type union32 is array (integer range 1 to 4) of std_logic_vector(7 downto 0);
end entity;
architecture fee of union is
signal UartData: std_logic_vector(7 downto 0);
function toquad (inp: std_logic_vector(31 downto 0)) return union32 is
begin
return union32'(inp(31 downto 24), inp(23 downto 16),
inp(15 downto 8), inp( 7 downto 0));
end function;
begin
TEST:
process
variable quad: union32;
constant fourbytes: std_logic_vector(31 downto 0) := X"deadbeef";
begin
quad := toquad (fourbytes);
for i in union32'RANGE loop
wait for 9.6 us;
UartData <= Quad(i);
end loop;
wait for 9.6 us; -- to display the last byte
wait; -- one ping only
end process;
end architecture;
And gives the same answer.

Resources