I have 3 questions however:
1.
Code VHDL - [expand] |
1
| D_sig1 <= D when (Load = '1') else Q_sig; |
I suppose that D_sig1 is Q_sig and D is D_Sig right?
No, 'D_sig1' is a typo, it should be 'D_sig' like this...
Code VHDL - [expand] |
1
| D_sig <= D when (Load = '1') else Q_sig; |
I'm assuming an entity like this:
Code VHDL - [expand] |
1
2
3
4
5
6
| entity Loadable_Reg is
port (d : in std_logic_vector(1 to 4);
clk : in std_logic;
load : in std_logic;
q : out std_logic_vector(1 to 4));
end Loadable_Reg; |
2. in the port mapping, you set 'clear' to 0, according to the D FF I've posted, if clear is '0', then the output 'q' is always '0'.
Then either
- 'clear' is not named very well. Usually if a signal is active low (i.e. a low logic level '0' means 'true') then you indicate as such in the name so that people (like me) looking quickly don't have to dig into the code to see what it does. The usual convention is for such a signal to have an '_n' suffix. One should be able to discern the function of a signal based on the port name in the entity. You shouldn't have to look at the architecture. Suppliers of parts will typically put an overbar in the name, but you can't do that in simple text file.
- Maybe 'clear' is not implemented as intended in dff. Perhaps the 'q' outputs should be cleared when 'clear = 1', not when it is 0.
3. What happens in the case when, clock = '0', clear ='1', preset='0' and Load='0'?
Well, since there is no rising edge on clock, you're not clearing or presetting the flops, so according to the logic inside dff, the output 'q' should maintain the current state whatever that is.
Modelsim, simulation gives me X in some of the signals of the output(Q_sig). I can provide you with a screenshot of the simulation if you want.
If there has been no rising edge or clear or preset then the outputs of the flops should be unknown. However, once one of those things
does happen they should take on definite values.
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
| library IEEE;
use IEEE.std_logic_1164.all;
use work.dff;
entity bitreg4 is
port (Clk_sig: in std_logic;
Load : in std_logic;
--D : in std_logic_vector(1 to 4);
D_sig : in std_logic_vector(1 to 4);
Q_sig : out std_logic_vector(1 to 4));
end bitreg4;
architecture bhv of bitreg4 is
begin
Dff1 : entity work.dff port map (d => D_sig(1), preset => '0', clear => '1', clk => Clk_sig,q => Q_sig(1));
Dff2 : entity work.dff port map (d => D_sig(2), preset => '0', clear => '1', clk => Clk_sig,q => Q_sig(2));
Dff3 : entity work.dff port map (d => D_sig(3), preset => '0', clear => '1', clk => Clk_sig,q => Q_sig(3));
Dff4 : entity work.dff port map (d => D_sig(4), preset => '0', clear => '1', clk => Clk_sig,q => Q_sig(4));
process(Clk_sig,D_sig,Load)
begin
if Load = '1' then
Q_sig <= D_sig;
end if;
end process;
end bhv; |
Your process drives the bits in 'Q_sig'. But the four instances of 'dff' also drives these bits. So you have two things driving 'Q_sig' which will cause unknowns as well if the process and the flip flop don't happen to agree on what they are driving. For example, if the process is trying to set Q_sig(1) to a value of '1', but 'dff' is trying to set it to '0', then the result is an 'X'. If 'dff' happened to want to also drive the bit to '0', then the result would be '0'. The correction needed is to use the typo corrected statement from my first post (however read my sidebar on multiple drivers before fixing).
Code VHDL - [expand] |
1
| D_sig <= D when (Load = '1') else Q_sig; |
The 'D' input to the flip flop 'dff', must be muxed to provide the proper input to dff. If 'Load' is not true, you don't want to change the value of 'Q', which means you must take the 'Q' output of 'dff' and loop it back to the 'D' input of 'dff'. This is exactly what the statement above does. This means that you need to change your bitreg4 entity to have an input 'D' (which you had but commented out).
One other comment on the entity you posted: you have 'Q_sig : out std_logic_vector(1 to 4));' but since 'Q_sig' is used internally in the entity it is not strictly an output. You have a couple of choices for fixing:
- Change 'Q_sig' from type 'out' to type 'buffer'
- Make the entity output 'Q' rather than 'Q_sig' (as you originally probably had) and add a statement 'Q <= Q_sig;'. This statement then connects the 'Q_sig' outputs from the 'dff' to the output of your bitreg4 entity.
Sidebar on multiple drivers:
An easier way to catch multiple drivers on signals that are only supposed to be driven from one place is to use type std_ulogic rather than std_logic; std_ulogic_vector rather than std_logic_vector. The compiler will flag the error, you won't have to debug to find that the problem is that there are two drivers. In this instance, I would suggest that before you make the change for 'D_sig1 <= ...' that you change all of the 'std_logic*' to 'std_ulogic*', compile and see the error. THEN make the change for 'D_sig1 <= ...' and see that the compiler is happy again. No debug necessary.
If you are forced to use std_logic rather than std_ulogic, then get used to the Modelsim command 'drivers'. This command will list all of the things that are driving a given signal and tell you how they are attempting to drive them as well as the end result.
[soapbox on]Type std_logic gets drilled into everybody's head that it is the proper choice for logic signals...and it's not. The proper type for any signal that only has one driver (which is most signals by the way) is std_ulogic. The type checking system of VHDL and the std_logic_1164 package create this simple way to correctly create a design and have the compiler catch this simple (but common) type of mistake, but boneheads continue the practice of preaching that std_logic is the right choice. It's not, it never has been and never will be. But that's OK, I don't spend time debugging to find multiple drivers on a signal that is intended to have only one...everyone else can if they want to, it's their time to waste.[soapbox off]
Kevin Jennings