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
Related
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).
I have code designed for Vivid software. How I can translate this code into ModelSIM? In vivado, I should get the following values, but in modelsim I get completely different ones.
This is noise generator. Successful in adding pseudorandom noise sequence to our sine wave, but now we are trying to add Gaussian noise. The code and the simulation results for ADDITION OF PSEUDORANDOM NOISE SEQUENCE TO SINE WAVE IS GIVEN BELOW:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; --try to use this library as much as possible.
entity sine_wave is
generic ( width : integer := 4 );
port (clk :in std_logic;
random_num : out std_logic_vector (width-1 downto 0);
data_out : out STD_LOGIC_VECTOR(7 downto 0)
);
end sine_wave;
architecture Behavioral of sine_wave is
signal data_out1,rand_temp1,noisy_signal : integer;
signal noisy_signal1 : STD_LOGIC_VECTOR(7 downto 0);
signal i : integer range 0 to 29:=0;
--type memory_type is array (0 to 29) of integer;
type memory_type is array (0 to 29) of std_logic_vector(7 downto 0);
--ROM for storing the sine values generated by MATLAB.
signal sine : memory_type := ("01001101","01011101","01101100","01111010","10000111","10010000","10010111","10011010","10011010");
--hi
begin
process(clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
variable temp : std_logic := '0';
begin
--to check the rising edge of the clock signal
if(rising_edge(clk)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
--data_out <= sine(i);
i <= i+ 1;
if(i = 29) then
i <= 0;
end if;
end if;
data_out <= sine(i);
data_out1<=to_integer(unsigned(sine(i)));
random_num <= rand_temp;
rand_temp1<=to_integer(unsigned(rand_temp));
noisy_signal<=data_out1+rand_temp1;
noisy_signal1<= std_logic_vector(to_signed(noisy_signal,8));
end process;
end Behavioral;
Vivado
ModelSIM
What I am trying to do is as follows:
I am taking few elements of an array, comparing them with a fixed value and trying to create a vector out of it.
Here is a piece of code:
architecture behav of main_ent is
...
type f_array is array(0 to 8) of std_logic_vector(7 downto 0);
signal ins_f_array: f_array;
signal sel_sig_cmd : std_logic_vector(3 downto 0);
...
process begin
sel_sig_cmd <= ((ins_f_array(4) = x"3A")&(ins_f_array(3)= x"3A")&(ins_f_array(2)= x"3A")&(ins_f_array(1)= x"3A"));
....
end process;
...
This should give something like sel_sig_cmd = 1000 or may be 1011 etc. But this is not working. Is there any alternative to this code? cheers Tahir
This is because the = function in VHDL returns a boolean, not a std_logic.
In VHDL '93, there is no tidy way to do this, other than set each bit manually:
sel_sig_cmd(3) <= '1' when (ins_f_array(4) = x"3A") else '0'
sel_sig_cmd(2) <= '1' when (ins_f_array(3) = x"3A") else '0'
-- etc
but in VHDL 2008, there are the relational operators (?= ?/= etc), that return std_logic on compare. So your code becomes:
sel_sig_cmd <= ( (ins_f_array(4) ?= x"3A")
& (ins_f_array(3) ?= x"3A")
& (ins_f_array(2) ?= x"3A")
& (ins_f_array(1) ?= x"3A") );
The answer from Tricky is a good one to follow. However, if you want to implement it in a process, then the process can be rewritten as follows :
architecture behav of main_ent is
...
type f_array is array(0 to 8) of std_logic_vector(7 downto 0);
signal ins_f_array: f_array;
signal sel_sig_cmd : std_logic_vector(3 downto 0);
...
process(ins_f_array(4 downto 1)) begin
if ((ins_f_array(4) = x"3A")&(ins_f_array(3)= x"3A")&
(ins_f_array(2)= x"3A")&(ins_f_array(1)= x"3A")) then
sel_sig_cmd <= "XXXX" -- Enter your desired value
....
end process;
...
This process would be tedious though as it has to cover all the 16 possibilities of the "if condition".
Another implementation is to use an if condition for each bit as follows :
architecture behav of main_ent is
...
type f_array is array(0 to 8) of std_logic_vector(7 downto 0);
signal ins_f_array: f_array;
signal sel_sig_cmd : std_logic_vector(3 downto 0);
...
process(ins_f_array(4 downto 1)) begin
if (ins_f_array(4) = x"3A") then
sel_sig_cmd(3) <= "X" -- Enter your desired value
else
sel_sig_cmd(3) <= "X" -- Enter your desired value
end if;
-- Repeat for other bits
....
end process;
...
You can overload the "=" operator :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb is
end entity;
architecture behav of tb is
function "=" (Left, Right: std_logic_vector) return std_logic is
begin
if (Left = Right) then
return '1';
else
return '0';
end if;
end function "=";
type f_array is array(0 to 8) of std_logic_vector(7 downto 0);
signal ins_f_array: f_array := (x"00",x"01",x"02",x"03",x"04",x"05",x"06",x"07",x"08");
signal sel_sig_cmd : std_logic_vector(3 downto 0);
begin
process (ins_f_array(1 to 4)) begin
sel_sig_cmd <= ((ins_f_array(4) = x"3A")&(ins_f_array(3) = x"3A")&(ins_f_array(2) = x"3A")&(ins_f_array(1) = x"3A"));
end process;
process
begin
wait for 10 us;
for i in 0 to 8 loop
ins_f_array(i) <= std_logic_vector(unsigned(ins_f_array(i)) + 1);
end loop;
end process;
end architecture;
I am in the process of trying to write some code that will simply just shift a 32 bit vector left or right, with a 5 bit input that will be used for the shift amount (shamt). The issue I am having is trying to convert an std_logic_vector to an integer. My code is this:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x : in std_logic_vector(31 downto 0);
shamt : in std_logic_vector( 4 downto 0);
y : out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
signal shift : integer;
signal temp : std_logic_vector(31 downto 0);
begin
shift <= conv_integer(unsigned(shamt));
temp <= x(shift downto 0);
y <= temp;
end beh;
The code is not complete I know, but to test some ideas I am trying to pass "00010" (2) into shamt, but shift comes out to be -2147483648. But I cannot figure out why it is doing this, nor can I find any resources online that shows anything different than what I am doing. I greatly appreciate any help.
-2147483648 (-2**31) is the default initial value for integers, being the leftmost, most negative value in its range. It suggests that the signal assignment to shift has not executed. Most likely because it is a continuous assignment and there hasn't been an event on shamt to cause it to update.
std_logic_arith is not an IEEE standard library. You should use to_integer() from ieee.numeric_std instead. It is also beneficial to keep numeric ports as unsigned or signed so that your intent is clear and to minimize type conversions. Also, you cannot directly assign the variable length slice of x to temp since their lengths do not match. You should use resize() (from numeric_std) to extend the length back to 32-bits or rethink your approach.
I fixed the obvious typo in the entity name, started the simulation (ModelSim) and forced the signal shamt to "00010". Then just after trying to run for 1 ps, ModelSim complains about:
Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 0 (-2147483648 downto 0 (null array)).
Time: 0 ps Iteration: 0 Process: /shiftlogical/line__16 File: shiftlogical.vhdl
Fatal error in Architecture beh at shiftlogical.vhdl line 16
That is because all your concurrent statements are executed in parallel. The new signal values are scheduled for the next delta cycle within the simulation. Thus, the line
temp <= x(shift downto 0);
is executed with the old value of shift which is the initial value of this signal. The initial value of an integer is -2**31 as also Kevin pointed out.
Of course you can initialize the signal shift, but the only value which will not result in an error will be 31 because in this asignment the signal on the left and the expression on the right must match in array (std_logic_vector) size. The signal shamt must be forced to "11111" as well, so that shift keeps 31.
You cannot easily fix this, because for a left shift you must add zeros at the right (LSB) and for a right shift zeros or the sign at the left (MSB).
#Martin Zabel what I had really tested there was to see if shift would hold an integer value which it did until I tried to pass it in for temp <= x(shift downto 0); What I realized was that the signal needed to really be a variable to work as intended and as follows my code consists of:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x: in std_logic_vector(31 downto 0);
shamt: in std_logic_vector(4 downto 0);
dir: in std_logic;
y: out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
begin
process(dir)
variable shift : integer;
begin
shift := conv_integer(unsigned(shamt));
if(dir = '0') then --Left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
elsif(dir = '1') then --Right shift
y(31-shift downto 0) <= x(31 downto shift);
y(31 downto 31-shift) <= (others => '0');
else --Always left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
end if;
end process;
end beh;
As part of an alu design for a FPGA course I need to build a Shift unit capable of doing left shift and right arithmetic shift.
I wrote some VHDL code, simulated it in ModelSim and it worked fine. The next step was to compile it for an FPGA (ALTERA DE1). Now all the other operations of the ALU works fine but not the shift unit. For opcodes related to shift the output stays equals to the input.
entity Shift is
generic (
N : integer := 8 );
port (
A,B:in std_logic_vector(N-1 downto 0);
OP: in std_logic_vector(2 downto 0);
Enable: in std_logic;
shiftedA:out std_logic_vector(N-1 downto 0));
end Shift;
architecture rtl of Shift is
begin
shift_process: process (Enable,op,A,B)
variable TempVec : std_logic_vector(N-1 downto 0) ;--:= (others => '0');
variable inVector : std_logic_vector(N-1 downto 0);
variable bitNum : Integer;
begin
inVector:=A;
TempVec:=A;
bitNum := conv_integer(B);
test <= "00000000";
if Enable = '1' then
if OP = "100" then
for i in 1 to bitNum loop
TempVec := TempVec(N-2 downto 0) & "0";
end loop ;
elsif OP = "101" then
for j in 1 to bitNum loop
TempVec := A(N-1) & TempVec(N-1 downto 1);
end loop;
else
TempVec := (others => '0');
end if;
else
TempVec := (others => '0');
end if;
shiftedA <= TempVec;
end process;
end rtl;
What am I doing wrong?
Loops, like for i in 1 to bitNum loop are unrolled in synthesis for implementation as a circuit, but in this case the end condition for the loop is dependent on data, since bitNum is conv_integer(B), so conversion into hardware is a problem. Simulators can handle such constructions, since they do not convert into a circuit.
There is probably a synthesis warning telling this, so check the warnings, since some are actually relevant.
Telling more will spoil a good exercise... ;-)