Undefined output of Ring Counter Test waveform

2019-07-22 16:00发布

问题:

I have modeled 4 bit Ring Counter using D Flip Flop.

The D flip flop is in separate file, included in my workspace. The D flip flop works correctly (gives correct output waveform).

This is the code of ring counter:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity ring4counter is
    port (
        clk: std_logic;
        output: out std_logic_vector(3 downto 0));
end ring4counter;

architecture ring4counter_arch of ring4counter is
    component dff
    port (
        clk: std_logic;
        d: in std_logic;
        q: out std_logic;
        qbar: out std_logic);
    end component;

    signal temp:std_logic_vector(3 downto 0):=(others=>'0');
begin
    r1: dff port map(clk, temp(3), temp(0));
    r2: dff port map(clk, temp(0), temp(1));
    r3: dff port map(clk, temp(1), temp(2));
    r4: dff port map(clk, temp(2), temp(3));
    output <= temp;
end ring4counter_arch;

Here is the testbench code for Ring counter:

library ieee;
use ieee.std_logic_1164.all;

entity ring4_tb is end ring4_tb ;

architecture arch of ring4_tb is
    component tbc is
    port (
        clk: std_logic;
        output: out std_logic_vector(3 downto 0));
    end component ;

    component dff
    port (
        clk: std_logic;
        d: in std_logic;
        q: out std_logic;
        qbar: out std_logic);
    end component;

    constant period : time := 50 ns ;

    signal clk      : std_logic := '0' ;    
    signal done     : boolean := false ;
    signal output   : std_logic_vector(3 downto 0) ;

    shared variable cycle : natural := 0 ;

    signal temp:std_logic_vector(3 downto 0):=(others=>'0');

begin
-- this is the unit under test
    u1: tbc
    port map(
        clk    => clk,
        output => output) ;

    clkprocess: process(done, clk)
    begin
    if (not done) then
        if (clk = '1') then
        cycle := cycle + 1 ;
        end if ;
        clk <= not clk after period / 2 ;
    end if ;
    end process ;

    r1: dff port map(clk, temp(3), temp(0));
    r2: dff port map(clk, temp(0), temp(1));
    r3: dff port map(clk, temp(1), temp(2));
    r4: dff port map(clk, temp(2), temp(3));
    output <= temp;

    testbench: process
    begin
    wait until (clk = '0') ;
    temp <= "1000";
    wait for period*4 ;

    done <= true ;      -- force the clock process to shutdown
    wait ;          -- this waits forever
    end process ;
end arch ;

But the waveform for 'output' is 'U' for all bits. Where am I going wrong?

回答1:

In the testbench process when you are trying to initialize temp to "1000", the flip flops are still driving the temp signal as well, so you effectively have a bus fight going on.



回答2:

Use the initialisation of temp in your ring counter to set up the signal.

Note that this may not synthesize correctly depending on your architecture and synthesis tool.

The most general purpose way of doing it is to add a reset signal to all the DFFs except on, and put a preset signal on that one. Then you assert the reset at the start, which will set up the DFFs to a good value.

Here's a simpler version of your code which does that and avoid the need to use explicit DFFs. You can also change the width of temp and the code will do all the rest for you:

process (clk)
begin
   if reset = '1' then
      temp <= (0=>'1', others => '0'); -- set one bit high, the others low.
   elsif rising_edge(clk) then
      -- take the high bit and move it to the low bit. 
      -- Move the other bits left 1 place
      temp <= temp(temp'high-1 downto 0) & temp(temp'high);
   end if;
end process;

(Note: code just typed into the message, there may be syntactic typos in there!)


BTW, shared variables are a bad idea unless they are of protected types. They can have race conditions.



回答3:

One thing to do is add a enable signal to D flipflops. when you want to reset the circuit make the enable signal go low and then change the temp to "1000".

r1: dff port map(clk, temp(3), temp(0), enable);

process(clk,reset)
begin
if(rising_edge(clk)) then
 if( reset='1') then
  enable='0';
  temp <= "1000";
 else
  enable <= '1';
 end if;
end if;
end process;