EmbDev.net

Forum: FPGA, VHDL & Verilog 16 bit PISO register


Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
I am trying to write the VHDL code for a synchronous 16 bit register 
(SIPO, asynchronous reset) to use it as a component in another Serial 
Multiplier code.

I have been struggling with 'U' output on my signal:

code:
library ieee;
use ieee.std_logic_1164.all;

entity ShiftRegister is
  port(A: IN std_logic_vector (15 downto 0);
       clk,load,reset: IN std_logic;
       Y: OUT std_logic);
end ShiftRegister;

architecture behavior of ShiftRegister is
signal tmp: std_logic_vector(15 downto 0);
begin
tmp <= (others => '0');

process (reset,clk)
begin
  if (reset = '1') then
    Y <= '0';
  end if;
end process;

process (load, A)
begin
  if (load = '1') then
    tmp <= A;
  else 
    tmp <= (others => '0');
  end if;
end process;

process (clk)
begin
if (clk = '1' and clk'EVENT) then
  Y <= tmp(0);
  tmp <= '0' & tmp(15 downto 1);
end if;
end process;


end behavior;

Test Bench:
library ieee;
use ieee.std_logic_1164.all;

entity tb_ShiftRegister is
end tb_ShiftRegister;

architecture behavior of tb_ShiftRegister is
component ShiftRegister
  port(A: IN std_logic_vector(15 downto 0);
       clk,load,reset: IN std_logic;
       Y: OUT std_logic);
end component;

signal A: std_logic_vector (15 downto 0);
signal clk,load,reset,Y: std_logic:= '0';

begin
clk <= not clk after 10 ns;
DUT: ShiftRegister port map (A,clk,load,reset,Y);
process
begin
  wait for 0 ns;
  reset <= '1'; load <= '1'; A <= "1010101010101010";
  wait for 320 ns;
  --A <= "1111000011110000";
  --wait for 320 ns;
end process;
end behavior;

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
*PISO

correction!

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
Here is what I've managed to code (still no go). The processes do not 
seem to return different Y values but I still get 'U'
library ieee;
use ieee.std_logic_1164.all;

entity ShiftRegister is
  port(A: IN std_logic_vector (15 downto 0);
       clk,load,reset: IN std_logic;
       Y: OUT std_logic);
end ShiftRegister;

architecture behavior of ShiftRegister is
signal tmp: std_logic_vector(15 downto 0):=(others => '0');
signal F: std_logic:='0';
begin
--tmp <= (others => '0');

process (reset,clk,A)
begin
if (reset = '1') then
  F <= '0';
elsif (clk = '1' and clk'event) then
  F <= tmp(0);
  tmp <= '0' & tmp(15 downto 1);
else
  F <= F;
end if;
end process;

process (load,A)
begin
if (load = '1') then
  tmp <= A;
end if;
end process;
Y <= F;

end behavior;

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> but I still get 'U'
Now the question arises: What is 'U'?
'U'ndefined, 'U'seless, 'U'ncertain, 'U'ninitilized?
   reset <= '1'; load <= '1'; A <= "1010101010101010";
   wait for 320 ns;
Shouldn't you do anything with load and reset afterwards?

After having managed that you will encounter serious problems with this 
here:
architecture behavior of ShiftRegister is
signal tmp: std_logic_vector(15 downto 0);
begin
tmp <= (others => '0');            -- tmp is ALWAYS reset to all zero!

process (reset,clk)
begin
  if (reset = '1') then
    Y <= '0';
  end if;
end process;

process (load, A)
begin
  if (load = '1') then
    tmp <= A;                      -- ADDITIONALLY sometimes tmp gets the value of A
  else 
    tmp <= (others => '0');        -- if not is is reset to zero ONCE MORE
  end if;
end process;

process (clk)
begin
if (clk = '1' and clk'EVENT) then
  Y <= tmp(0);                                 
  tmp <= '0' & tmp(15 downto 1);   -- ADDITIONALLY sometimes its shifted with a clock
end if;
end process;

end behavior;
All in all: you drive tmp from three sources. That will not work! it 
will result in a collision. And
BTW: the very same is for Y! It is driven from two sources...
In fact you cannot reset Y because its the very same signal as tmp(0)!
Why should you need here a reset signal at all?

Try it that way and think hard about it:
architecture behavior of ShiftRegister is
  signal tmp: std_logic_vector(15 downto 0) := (others=>'0');
begin
  process (clk,load,A)
  begin
    if (load = '1') then
      tmp <= A;
    elsif (clk = '1' and clk'EVENT) then                              
      tmp <= '0' & tmp(15 downto 1);
    end if;
  end process;

  Y <= tmp(0);                                 
end behavior;

: Edited by Moderator
Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
Aren't all processes treated as concurrent statements within 
architecure? So only when one of the elements in the sensitivity list 
changes do they run again, correct? That means only processes with 
changes in their SL will get re-evaluated. Do I understand this 
correctly?

And the code that you provided (theoretically, I cannot simulate it now) 
does not work as intended. This is because tmp is reset to A everytime 
the process runs so we won't truly get the serial output of A, just 
continuous A(0)'s.

Author: P. K. (pek)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> So only when one of the elements in the sensitivity list
> changes do they run again, correct? That means only processes with
> changes in their SL will get re-evaluated. Do I understand this
> correctly?

From the point of view how the Simulator calculates the result of each 
process this is correct, but: The other processes that are not 
re-evaluated still drive the signals (with the same not re-evaluated 
values as before).

In fact, it is only the simulator that makes use of sensitivity lists 
(to know when it needs to calculate new values). The hardware that 
results from synthesis just permanently "is there".

: Edited by User
Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> Do I understand this correctly?
Just for the simulation this is (nearly) correct. But in hardware each 
process is realized in parallel to each other process and "it" will 
drive its value all the time...

> And the code that you provided (theoretically, I cannot simulate it now)
> does not work as intended.
It works as far as my intention was: I load a value int the shift 
register by assigning a value to A and setting load to '1'. AFTERWARDS 
i set load to '0' and start clocking the data out. Got the trick?

And do you remeber my question:
Lothar Miller wrote:
>  reset <= '1'; load <= '1'; A <= "1010101010101010";
>  wait for 320 ns;
> Shouldn't you do anything with load and reset afterwards?

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
I understand. But the assignment requires that Load remains 1 when we 
are clocking out an output and 0 if we want to clear the register.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> But the assignment requires
Which one?
> that Load remains 1 when we are clocking out
> an output and 0 if we want to clear the register.
And how do you LOAD data to the shift register? And if load also 
clears the register: what is the reset for?

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
By assignment I was referring to my assignment

Reset clears the output to zero regardless of load. When reset is zero, 
content is zero if load is zero and is filled with Din when load is one. 
That is why load and A are in a separate process that is sensitive to 
both but not reset or clock.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> When reset is zero, content is zero if load is zero and is filled with
> Din when load is one.
A very unusual behavior. For a pity there is no hardware inside a FPGA 
able to handle such behavior...

> That is why load and A are in a separate process
> that is sensitive to both but not reset or clock.
You think the wrong way! You cannot control hardware stucture with the 
sensitivity list. The sensitivity lust is only relevant for the 
simulator.

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
Are you saying I cannot use both load and reset?

Author: Omar Rashad (Guest)
Posted on:

Rate this post
0 useful
not useful
Can you show me a code you would write to describe a PISO 16 bit 
register (clocked) ?

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Omar Rashad wrote:
> Can you show me a code you would write to describe a PISO 16 bit
> register (clocked) ?
I did already. Tomorrow I will provide a simple testbench for it...

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Ok, here we go.
My spec is:
1. when load is '1' then load the vector A to the shift register
2. when load is '0' then shift out the data bit LSB first through Y
And this is the result:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Piso is
    Port ( clk :  in   STD_LOGIC;
           load : in   STD_LOGIC;
           A :    in   STD_LOGIC_VECTOR (15 downto 0);
           Y :    out  STD_LOGIC);
end Piso;

architecture Behavioral of Piso is

  signal sr: std_logic_vector(15 downto 0) := (others=>'0');

begin

  process (clk,load,A)
  begin
    if (load = '1') then
      sr <= A;
    elsif rising_edge(clk) then
      sr <= '0' & sr(15 downto 1);
    end if;
  end process;

  Y <= sr(0);      
 
end Behavioral;

Using this testbench I get the waveform in the screenshot:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
ENTITY tb_piso IS
END tb_piso;
 
ARCHITECTURE behavior OF tb_piso IS 
 
    COMPONENT Piso
    PORT(
         clk : IN  std_logic;
         load : IN  std_logic;
         A : IN  std_logic_vector(15 downto 0);
         Y : OUT  std_logic
        );
    END COMPONENT;

   signal clk : std_logic := '0';
   signal load : std_logic := '0';
   signal A : std_logic_vector(15 downto 0) := (others => '0');
   signal Y : std_logic;

BEGIN
 
   uut: Piso PORT MAP (
          clk => clk,
          load => load,
          A => A,
          Y => Y
        );

   clk <= not clk after 5 ns;

   process  begin    
      A <= x"5555";
      load <= '1';
      wait for 15ns;
      load <= '0';
      wait for 200ns;

      A <= x"CCCC";
      load <= '1';
      wait for 15ns;
      load <= '0';
      wait for 200ns;

      A <= x"F0F0";
      load <= '1';
      wait for 15ns;
      load <= '0';
      wait for 200ns;

      wait;
   end process;

END;

The PISO is synthesizeable and results in 16 D-Flipflops with 
asynchronous clrear and preset inputs, which are controlled from A with 
a little glue logic. See the RTL schematic for this result...

: Edited by Moderator

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.