8 bit serial to parallel shifter in vhdl - 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).

Related

VHDL : Internal signals are undefined even when defined in the architecture declaration section

So I've been working on some homework for my VHDL course and I can't seem to understand this problem.
The point here is to create the adder/subtractor of an ALU that works both on 2's complement and unsigned 32-bit buses, which is why I have a condition called sub_mode ( A - B = A + !B + 1 ) which will also be the carry-in when activated.
The rest of the different inputs and outputs are pretty self-explanatory.
My problem is with the testbenching of such component where, even though carry_temp and r_temp have been initialized in declaration section of the architecture, end up showing up undefined. I have guessed that it is due to the for loop within the process screwing everything up. Would that be an accurate guess? And if yes, is it possible to proceed to add two bit buses together without having to fully create an n-bit adder made from n 1-bit adder components?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add_sub is
port(
a : in std_logic_vector(31 downto 0);
b : in std_logic_vector(31 downto 0);
sub_mode : in std_logic;
carry : out std_logic;
zero : out std_logic;
r : out std_logic_vector(31 downto 0)
);
end add_sub;
architecture synth of add_sub is
signal cond_inv : std_logic_vector(31 downto 0);
signal carry_temp : std_logic_vector(32 downto 0) := (others => '0');
signal r_temp : std_logic_vector(31 downto 0) := (others => '0');
begin
behave : process(a,b,sub_mode)
begin
if sub_mode = '1' then
cond_inv <= b xor x"ffffffff";
else
cond_inv <= b;
end if;
carry_temp(0) <= sub_mode;
for i in 0 to 31 loop
r_temp(i) <= a(i) xor cond_inv(i) xor carry_temp(i);
carry_temp(i+1) <=
(a(i) and cond_inv(i)) or
(a(i) and carry_temp(i)) or
(cond_inv(i)and carry_temp(i));
end loop;
if r_temp = x"00000000" then
zero <= '1';
else
zero <= '0';
end if;
r <= r_temp;
carry <= carry_temp(32);
end process behave;
end synth;

how to increment 5 bit numbers in 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.

Issue with using component and forloop in VHDL

I am trying to create a component for division in VHDL, below is my code. I dont know where i am going wrong. My logic is:
At every step,
• shift divisor right and compare it with current dividend
• if divisor is larger, shift 0 as the next bit of the quotient
• if divisor is smaller, subtract to get new dividend and shift 1
as the next bit of the quotient.
I have used '-' sign here but in actual i have to use gates so either i have to use my subtraction component or just create a subtractor here.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
ENTITY divprog IS
PORT(
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
err: OUT std_logic;
reslow: OUT std_logic_vector(3 downto 0);
reshigh: OUT std_logic_vector(3 downto 0));
END divprog;
architecture behaviour of divprog is
signal ax,bx,bsub,res :std_logic_vector(7 downto 0) := (others => '0');
signal quo: std_logic_vector(3 downto 0) := (others => '0');
signal intcarry: std_logic_vector(8 downto 0):= (others => '0');
BEGIN
--sub1: subtractor PORT MAP(aa,bb,x,ss);
Process is
variable i : POSITIVE := 1;
BEGIN
ax <= "0000" & a;
bx <= b & "0000";
if(b > "0000") then
while (i <=3) loop
bx <= '0'&bx(7 downto 1);
IF (ax < bx) then
quo <= quo(2 downto 0)& '0';
--bx <= '0'&bx(7 downto 1);
res <=ax;
elsif(ax >= bx) then
res <= ax - bx;
quo <=quo(2 downto 0)& '1';
end if;
i := i + 1;
ax <= res;
end loop;
reshigh <= quo;
reslow <= res(3 downto 0);
end IF;
wait for 100 ns;
END PROCESS;
end behaviour;
Can please someone help me with this?
Thanks
The functional problem is related to variable i. It gets stuck at 4 after the first 100ns. It should be set to 1 between BEGIN and END PROCESS.

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.

VHDL n-bit barrel shifter

I have a 32 bit barrel shifter using behavior architecture. Now I need to convert it to an n-bit shifter. The problem that I'm facing is that there is some kind of restriction to the for loop that I have to put a constant as sentinel value.
Following is my Code
library IEEE;
use IEEE.std_logic_1164.all;
Entity bshift is -- barrel shifter
port (left : in std_logic; -- '1' for left, '0' for right
logical : in std_logic; -- '1' for logical, '0' for arithmetic
shift : in std_logic_vector(4 downto 0); -- shift count
input : in std_logic_vector (31 downto 0);
output : out std_logic_vector (31 downto 0) );
end entity bshift;
architecture behavior of bshift is
function to_integer(sig : std_logic_vector) return integer is
variable num : integer := 0; -- descending sig as integer
begin
for i in sig'range loop
if sig(i)='1' then
num := num*2+1;
else
num := num*2;
end if;
end loop; -- i
return num;
end function to_integer;
begin -- behavior
shft32: process(left, logical, input, shift)
variable shft : integer;
variable out_right_arithmetic : std_logic_vector(31 downto 0);
variable out_right_logical : std_logic_vector(31 downto 0);
variable out_left_logical : std_logic_vector(31 downto 0);
begin
shft := to_integer(shift);
if logical = '0' then
out_right_arithmetic := (31 downto 32-shft => input(31)) &
input(31 downto shft);
output <= out_right_arithmetic after 250 ps;
else
if left = '1' then
out_left_logical := input(31-shft downto 0) &
(shft-1 downto 0 => '0');
output <= out_left_logical after 250 ps;
else
out_right_logical := (31 downto 32-shft => '0') &
input(31 downto shft);
output <= out_right_logical after 250 ps;
end if;
end if;
end process shft32;
end architecture behavior; -- of bshift
any help will be appreciated
Your code is not a barrel shifter implementation, because a barrel shift is a mux-tree.
If you have a 32 bit BarrelShifter module, you will need a 5 bit Shift input, wherein every bit position i enables a 2^i shift operation.
So for example shift = 5d -> 00101b enables a mux in stage 1 to shift for 1 bit and a mux in stage 3 to shift 4 bits. All other mux stages are set to pass through (shift(i) = 0).
I also would not advice to mix up basic shifting with shift modes (arithmetic, logic, rotate) and directions (left, right).
arithmetic and logic is only different in the shift-in value
shift right can be done by a conversion => shiftright = reverse(shiftleft(reverse(input), n)
An open source implementation can be found here:
https://github.com/VLSI-EDA/PoC/blob/master/src/arith/arith_shifter_barrel.vhdl

Resources