How to use Constants and Generic Map in VHDL
ฝัง
- เผยแพร่เมื่อ 27 ส.ค. 2024
- Learn how to use Constants and Generic Map to make VHDL modules configurable. Bit widths and behavioral settings are often made configurable at instantiation time through the use of generics in VHDL.
The blog post for this video:
vhdlwhiz.com/c...
In this video we convert a 4-input, 8-bit multiplexer into a configurable bit width multiplexer. Generics are evaluated at compile time by the simulator or synthesis tool. Unlike Port Map, the Generic Map inputs cannot be changed at run-time, therefore you can only assign a value or a constant to them.
Constants in VHDL behave just like signals, the only difference is that you cannot change them dynamically. We use constants to avoid typing the same hard-coded value over and over again in our code. In this video we use a constant in our testbench to set the bit width of all the input signals and the output signal.
The ease with which the concepts are explained in this video is astonishing and very helpful. Thanks a lot
Thanks! I'm glad you found it helpful.
i wish i had found this channel at the start of term not a day before my final :(
I'm glad you liked my channel. I wish you luck on the exam. You can do this!!! 😎
I really need to send this URL to My lecturer. this is how you should build us. Thank you.
Thank you for your great work. We fully appropriate it.
I'm glad you found it helpful!
Thanks for making these, they are quite helpful.
Thank you very much
Welcome!
what will happen if you set the constant value to 4? The muxer output will still try to set 8 bit values to 4 bit wide signal - in a way its not very generic if the output values are hard-coded, can the output values be of programmable width?
never mind, I see you addressed that in another comment
For anyone using GHDL + gtkwave to do these tasks instead of ModelSim and are getting "error: integer overflow":
Replace `integer` in the generic argument of the module with `positive`.
That way we help ensure the compiler can prove we won't end up with a negative `DataWidth`.
Thank you!
Hello Jonas,
If we use a generic map for the bit length of our signals how will that be synthesized?
Since the value is only defined in the testbench , do we have to give it a definite value when we are happy with the perfomance of our design? Or the synthesis tool will get that value from the testbench?
That's going to synthesize to whatever length you assign to the generic map. If the module using generics is a submodule in our design, we assign a value to the generic map when we instantiate it, just like we did in the testbench. If the module using generics is the top module, you can assign a value to it from within the implementation software. In Xilinx Vivado it's in the Project Manager menu: Settings->Language Options->Generic/Parameters.
@@VHDLwhiz think I got it now! Thanks!
Thanks, dude!
The instantiation of the signals is not generic yet though. x"AA", x"BB" etc. assume an 8 bit value. Looking into ways how to make them generic too now.
Initialized them with this `others => '0'` now, and then created a one-time init process (having wait statmement at the end) in which different bits are set to '1' for each of them.
@@TheLeontheking It's better to use a function to create complex signal initialization rules.
Something like this:
constant datawidth : integer := 32;
-- Initialize to "....10101010"
function init_sig return std_logic_vector is
variable r : std_logic_vector(datawidth - 1 downto 0);
begin
for i in 0 to datawidth - 1 loop
if i mod 2 = 0 then
r(i) := '0';
else
r(i) := '1';
end if;
end loop;
return r;
end function;
-- s = x"AAAAAAAA"
signal s : std_logic_vector(datawidth - 1 downto 0) := init_sig;
if we change DataWidth we should change the width of Sel.
I don't think we need to do that unless I misunderstood something. Because we are still selecting between 4 signals of configurable width. We only need a two-bit Sel signal for that.
Is there anyway to estimate the datawidth in the generic block like that:
GENERIC(
device2address: integer:= 4; --number of device slaves
addwidth : INTEGER := integer(ceil(log2(device2address)))
);
Yes, but you will have to implement log2 yourself. It's not defined in any standard library that I know of. Or you can use signed/unsigned:
constant addwidth : unsigned(device2address - 1 downto 0);
In either case, you have to define the addwidth constant in the module, and not on the generic declaration. You can't use one generic constant to define another generic constant on the same entity.
# ** Fatal: (vsim-3350) Generic "DataWidth" has not been given a value.
this happens when i tried to copy past the code from this video,
and so i instantiate the value "DataWidth" in the generic declaration but the signal is "x"
how can i fix that?
You have to assign something to the generic when you instantiate the module: "generic map(DataWidth => 8)" or something. If I understand correctly, you figured that out.
When you say that the signal is 'X', I guess you mean the "Output" signal. According to the code, this will happen if Sel contains a value other than '0' or '1' or if one of the signals Sig1, Sig2, Sig3, or Sig4 contains 'X's. My bet is that you have not set Sel to anything, and it's therefore 'U' (Uninitialized).
@@VHDLwhiz my bad !
i just simulate both the MUX and test-bench file at the same time
fixed when i simulate only the test-bench file
thanks for your replay!