Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Time multiplexing with LED

Status
Not open for further replies.

eengr

Member level 4
Joined
Mar 9, 2016
Messages
75
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
4,270
Hi
I am working my way through FPGA prototypes with VHDL examples’ book by Pong P chu. I am trying to simulate the design in Listing 4.15 (dis_mux_test)

Which is as below:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.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 disp_mux_test is
    Port ( clk : in  STD_LOGIC;
           btn : in  STD_LOGIC_VECTOR (3 downto 0);
           sw : in  STD_LOGIC_VECTOR (7 downto 0);
           an : out  STD_LOGIC_VECTOR (3 downto 0);
           sseg : out  STD_LOGIC_VECTOR (7 downto 0));
end disp_mux_test;
 
architecture Behavioral of disp_mux_test is
 
    signal d3_reg, d2_reg : std_logic_vector (7 downto 0);
    signal d1_reg, d0_reg : std_logic_vector (7 downto 0);
    
begin
 
    disp_unit: entity work.disp_mux
        port map (
        clk => clk, reset => '0',
        in3 => d3_reg, in2 => d2_reg, in1 => d1_reg,
        in0 => d0_reg, an => an, sseg => sseg);
        -- registers for 4 LED patterns
        
        process (clk)
        begin
            if (clk'event and clk = '1') then
                if (btn(3) = '1') then
                    d3_reg <= sw;
                end if;
                if (btn(2) = '1') then
                    d2_reg <= sw;
                end if;
                if (btn(1) = '1') then
                    d1_reg <= sw;
                end if;
                if (btn(0) = '1') then
                    d0_reg <= sw;
                end if;
                
            end if;
        end process;
        
        
 
end Behavioral;




It calls for another VHDL file ‘disp_mux’ which is as below:




Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
library IEEE;
use IEEE.STD_LOGIC_1164.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 disp_mux is
    Port ( clk, reset : in  STD_LOGIC;
           in3, in2, in1, in0 : in  STD_LOGIC_VECTOR (7 downto 0); -- data input to be displayed on corresponding 7 seg
           an : out  STD_LOGIC_VECTOR (3 downto 0);
           sseg : out  STD_LOGIC_VECTOR (7 downto 0));
end disp_mux;
 
architecture Behavioral of disp_mux is
 
    -- refreshing rate around 800Hz (50MHz / 2^16) human eye wont see the difference
    -- Say if N = 5, we use last two bis as 'sel'
    -- With each riging edge of clk @ 50MHz we get the following
    -- 00 000
    -- 00 001
    -- 00 010
    -- .....
    -- .....
    -- 00 111
    -- 01 000
    -- 01 001
    -- ......
    -- ......
    -- 10 000
    -- ......
    -- ......
    -- ......
    -- This means that for 3 bits we get 8 (2^3) cycles before 5th & 4th bits change to "01"  its state 
    -- Then it goes for another 8 cycles before 5th & 4th bits change to "10" 
    -- & then another 8cycles before 5th & 4th bits are "11"
    -- So the refersh rate is 8 x 20ns = 160ns = 6.25MHz 
    -- So if we use 16 bits + 2 last bits for 'sel' 2^ 16 = 65536 cycles
    -- 66536 x 20ns = 1.3ms = 763 Hz = 800Hz apprx
    constant N: integer := 5; -- Change 5 to 18 as we need last two bits + 16 bits
    signal q_reg, q_next : unsigned (N-1 downto 0);
    signal sel : std_logic_vector (1 downto 0);
    
 
begin
    -- register
    process (clk, reset)
    begin
        if (reset = '1') then
            q_reg <= (others => '0');
        elsif (clk'event and clk = '1') then
            q_reg <= q_next;
        end if;
        end process;
        
    -- next state logic for counter
    q_next <= q_reg + 1;
    
    -- 2 MSBs of counter to control 4 - to -1 multiplexing
    
    sel <= std_logic_vector (q_reg (N-1 downto N-2));
    
    process (sel, in0, in1, in2, in3)
    begin
        case sel is
            when "00"       => 
                an <= "1110";
                sseg <= in0;
                
            when "01"       =>
                an <= "1101";
                sseg <= in1;
                
            when "10"       =>
                an <= "1011";
                sseg <= in2;
                
            when others     =>
                an <= "0111";
                sseg <= in3;
            
            end case;
            end process;
 
 
end Behavioral;



I changed the constant N to 5 instead of 18 so that I get ‘sel’ updated after 8 cycles (easier to see in simulation). I managed to simulate the file disp_mux and it works fine. Counter counting fine and I get sseg output updated regularly depending upon the ‘sel’ value

However, when I try to simulate ‘disp_mux_test’ file,

an fixed at 0111.png

It seems like ‘an’ output always staying @ “0111” & that should happen only when “sel” = “11”. So it looks like counter is not working OR I am doing something silly in my test bench.

My test bench is:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY tb1 IS
END tb1;
 
ARCHITECTURE behavior OF tb1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT disp_mux_test
    PORT(
         clk : IN  std_logic;
         btn : IN  std_logic_vector(3 downto 0);
         sw : IN  std_logic_vector(7 downto 0);
         an : OUT  std_logic_vector(3 downto 0);
         sseg : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    
 
   --Inputs
   signal clk : std_logic := '0';
   signal btn : std_logic_vector(3 downto 0) := (others => '0');
   signal sw : std_logic_vector(7 downto 0) := (others => '0');
 
    --Outputs
   signal an : std_logic_vector(3 downto 0);
   signal sseg : std_logic_vector(7 downto 0);
 
   -- Clock period definitions
   constant T : time := 20 ns;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: disp_mux_test PORT MAP (
          clk => clk,
          btn => btn,
          sw => sw,
          an => an,
          sseg => sseg
        );
 
   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for T/2;
        clk <= '1';
        wait for T/2;
   end process;
 
 
   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
        sw <= "01010101";
        btn(3) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(3) <= '0';
        
        --************************
        -- test btn(2) operation
        --************************
        btn(2) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(2) <= '0';
        --************************
        -- test btn(1) operation
        --************************
        sw <= "11110101";
        btn(1) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(1) <= '0';
        --************************
        -- test btn(0) operation
        --************************
        sw <= "11110101";
        btn(0) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(0) <= '0';
         --******************************
      --terminate Simulation
      --******************************
 
        
 
        assert false
        report "NS Simulation Completed"
        severity failure; 
   end process;
 
END;



Please help
 

Put q_reg and/or sel up in the simulation waveforms.

As you will see you didn't reset the q_reg and its value is X. So the last branch of the case is always taken.

Relying on others in a case statement IMO is idiotic (guess that means that author is an idiot :-?).
I once saw an article about apply X's to all output in others to detect problems with the case variables or values outside the design range during simulation.

To fix this generate a proper reset in the disp_mux_test file instead of assigning it to '0'.
 
  • Like
Reactions: eengr

    eengr

    Points: 2
    Helpful Answer Positive Rating
Thank you for your help.

Put q_reg and/or sel up in the simulation waveforms.

These signals are defined in disp_mux.vhd.

My test bench is for disp_mux_test.vhd

How would you normally map the testbench ports to map to the signals in disp_mux.vhd?

I mean one way I could think of is to use two additional ports as outputs in disp_mux.vhd say port_q & port_sel

I then assign signals q_reg & sel to the above two ports inside disp_mux.vhd.

& then inside disp_mux_test.vhd. I again define two output ports as say say port_q1 & port_sel1 & map these to these port of disp_mux.vhd
& then call them in test bench.

Is there any other shorter / elegant way of achieving this as well to access these signals in test bench?
As you will see you didn't reset the q_reg and its value is X. So the last branch of the case is always taken.

To fix this generate a proper reset in the disp_mux_test file instead of assigning it to '0'.

I have now created reset in disp_mux_test.vhd as an input port & mapped it to 'reset' of disp_mux.vhd

I did the simulation & it looks much better now as in the counter is working & 'an' value is changing. However, I see 'UUUUUUUU' @ sseg output when 'an' value is anything but the one corresponding to the actual button pressed.

See screen dump below:
an changing but sseg UUUU.png



My test bench code is:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY tb1 IS
END tb1;
 
ARCHITECTURE behavior OF tb1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT disp_mux_test
    PORT(
         clk, reset : IN  std_logic;
         btn : IN  std_logic_vector(3 downto 0);
         sw : IN  std_logic_vector(7 downto 0);
         an : OUT  std_logic_vector(3 downto 0);
         sseg : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
    
 
   --Inputs
   signal clk : std_logic := '0';
    signal reset : std_logic := '0';
   signal btn : std_logic_vector(3 downto 0) := (others => '0');
   signal sw : std_logic_vector(7 downto 0) := (others => '0');
 
    --Outputs
   signal an : std_logic_vector(3 downto 0);
   signal sseg : std_logic_vector(7 downto 0);
 
   -- Clock period definitions
   constant T : time := 20 ns;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: disp_mux_test PORT MAP (
          clk => clk,
             reset => reset,
          btn => btn,
          sw => sw,
          an => an,
          sseg => sseg
        );
 
   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for T/2;
        clk <= '1';
        wait for T/2;
   end process;
 --*************
    -- reset 
    --************* 
 
    reset <= '1', '0' after T/2;
 
   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
        sw <= "01010101";
        btn(3) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(3) <= '0';
        
        --************************
        -- test btn(2) operation
        --************************
        btn(2) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(2) <= '0';
        --************************
        -- test btn(1) operation
        --************************
        sw <= "11110101";
        btn(1) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(1) <= '0';
        --************************
        -- test btn(0) operation
        --************************
        sw <= "11110101";
        btn(0) <= '1';
        for i in 1 to 25 loop
            wait until falling_edge (clk);
        end loop;
        btn(0) <= '0';
         --******************************
      --terminate Simulation
      --******************************
 
        
 
        assert false
        report "NS Simulation Completed"
        severity failure; 
   end process;
 
END;




Does this mean that display output would be all over the place where UUUUUUUUs are seen in simulation?
 

Think about it, you didn't define all the d#_reg values in the disp_mux_test file, so of course they are undefined (Uninitialized) until you set them with the correct button press.

To debug, start with something that is wrong and trace it back through your code to find out how it is generated and determine what is wrong with the inputs, then trace those back. It is not that hard to do this and avoids having to ask questions to very simple problems, that you should be able to figure out with even a minor amount of effort. Besides developing a useful skill you will have your answers far quicker than waiting for someone to help you.
 
  • Like
Reactions: eengr

    eengr

    Points: 2
    Helpful Answer Positive Rating
Think about it, you didn't define all the d#_reg values in the disp_mux_test file, so of course they are undefined (Uninitialized) until you set them with the correct button press.
Thank you very much for your help

To debug, start with something that is wrong and trace it back through your code to find out how it is generated and determine what is wrong with the inputs, then trace those back. It is not that hard to do this and avoids having to ask questions to very simple problems, that you should be able to figure out with even a minor amount of effort. Besides developing a useful skill you will have your answers far quicker than waiting for someone to help you.

Yes you are absolutely correct. & I usually try doing this. But two issues that I struggle to deal with:

First -- on anything that I have not got experience working in for long, I have confidence issue as in even if I manage to get something to work (based on what I read) the way I wanted it to work, I think that I must have done something wrong somewhere that will result into bigger problem later on (it sounds funny or mental but I have had many examples of such work that I have done in the past & I have been doing little stupid things that I somehow miss during the design phase & then later on realise this when things are in use by other people).
So, I try to get it checked from experienced people such as here on this forum

Second - & this happens alot often, sometimes I tend to gave some sort of mental block and I miss obvious things or methods to follow & end up in confusion. I do get around this but sometimes it may take days (in one case it took months). That's why I ask. But yes you are correct when I eventually get around it myself, it gives me more confidence and the solution stays in my memory for long long time.

Like now in VHDL case, I have followed all the examples in this book Pong P Chu (up til Chapter-4). Based on feedback from this forum what I understand that it is better to have block level logic diagram of the solution before writing the code. Now, since yesterday I am struggling with coming up with such a diagram for programmable square wave generator (programmable ON & OFF time). (synchronous design)
But if one were to ask me how it could be designed in usually say C programming, even if I don't know the entire syntax of C-program but I am confident that I have an understanding of its implementation in C code. But when its gets to logic diagram of its working as in selecting the digital components (flip flop, counter, mux, interfacing them together to get the desired output function), I struggle.... (Getting frustrated and need to find a way around to get out of these problems in professional life....)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top