I am trying to generate single bit random number on every clock cycle in Verilog for testing purposes. I am doing this in a testbench module. Here is the code;
module tb;
// Inputs
reg clk;
reg in;
// Outputs
wire x;
// Instantiate the Unit Under Test (UUT)
single_bit uut (
.clk(clk),
.in(in),
.x(x)
);
integer seed=1;
initial
begin
clk=0;
forever
#5 clk=!clk;
in= $random(seed);
end
endmodule
But after simulation, I am getting constant value of 1 in seed, and in has x.
Any help is appreciated.
Your indentation is misleading. Here is how your code is parsed:
initial begin
clk=0;
forever #5 clk=!clk;
in= $random(seed);
end
Your code never reaches the assignment to in because you never reach the end of your forever loop. Since you declared in as a reg and you never assign a value to in, it retains its default value of x.
The assignment to in should be inside the forever loop. This generates a random stream of 0 and 1 for in at every clock edge:
initial begin
clk=0;
forever begin
#5 clk=!clk;
in = $random(seed);
end
end
Related
the temp variable is storing data out of its range. The range is used to store the maximum final value but it is holding the previous value and goes on incrementing. The functionality of for loop which is condition based is not satisfingenter image description here
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity counter is
Port (clk,rst:in std_logic;
o:out integer range 0 to 15
);
end counter;
architecture Behavioral of counter is
signal temp2:integer range 1 to 15:=0;
begin
process(clk) is
begin
if rising_edge(clk) then
if rst='1' then
temp2<=0;
else
for i in 1 to 15
loop
temp2<=temp2+1;
end loop;
end if;
end if;
end process;
o<=temp2;
end Behavioral;
Range puts a constraint on an object (here the signal temp2) that says it is illegal, and hence, fail if this object receives a value that is outside of the range.
Your code then must take the actions (such as mod) to make this so.
Since your code assigns the value 0, I am assuming that you need to update your declaration as follows:
signal temp : integer range 0 to 15 ;
. . .
temp2<= (temp2+1) mod 16;
I want to generate an automated input stimulus for my DUT. This input is going to different modules at the same time and working on this data. I want my input to be generated in an increasing manner. Like 0000,0001,0010,0011...1111
I tried using a for loop but it only uses the last data from the loop and works on that.
always_comb begin
for (i=0, i<16; i=i+1)
begin
data <= i;
end
end
When I give inputs individually like,
data = 8'd1;
#2;
data = 8'd2;
#2;
It works smoothly with all input values specified.
always_comb cannot have delays. At least per the IEEE1800 standard.
You can do something like this:
bit [3:0] data; // bit so the initial value is 0, not x
bit clk;
always #1 clk++; // or some other clock model
always_ff #(posedge clk) begin
data <= data+1;
end
or something like this:
logic [3:0] data;
initial begin
for (i=0, i<16; i=i+1) begin
data = i;
#2;
end
end
Or some other similar code with time delay.
I am really beginner in VHDL and I am trying to make a hot-n-cold game. My first goal is generating numbers between -1024 and 1024 so that I can use 10 switches to guess. However, there are a lot of sources about positive integers but I could not find any for negative ones. Here is a sample code of mine. Also, someone says LFSR does this job but I am new and I could not understand the behavior of LFSR.
library ieee;
use ieee.math_real.all;
entity rand_gen is
end rand_gen;
architecture behavior of rand_gen is
signal rand_num : integer := 0;
begin
process
variable seed1, seed2: positive;
variable rand: real;
variable range_of_rand : real := 1024.0;
begin
uniform(seed1, seed2, rand);
rand_num <= integer(rand*range_of_rand);
wait for 10 ns;
end process;
end behavior;
Please have a look at Open Source VHDL Verification Methodology. This framework offers many packages to ease writing of testbenches. For instance there is a RandomPkg VHDL package, that offers lots of randomization procedures, functions and a protected type for constrained random: RandInt(min, max).
process
variable RV : RandomPType;
begin
RV.Init("dkudbcsdkbcfsdbcfdsyc"); -- create a seed value
for in i 0 to 15 loop
rand_num <= RV.RandInt(-1024, 1024);
wait until rising_edge(Clock);
end loop;
end process;
The protected type will take care of handling the two seed integers, that you would need to handle manually if you use ieee.math_real.uniform(...)
I have a problem in synthesis with my VHDL code : I am trying to get the logarithm value of an input signal S_ink:
My code :
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1; --S_ink is an input of my entity (integer)
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
It works very well in simulation but doesn't synthesize.
The error message is : "While loop is not terminating. You can set the maximum of loop iterations with the syn_looplimit attribute"
However, this code synthesize (but that is not what I want)
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := 3000; -- a random constant value
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
When the synthesis tool translates the design, it will make a circuit with a topology that does not depend on the data values, but where the wires carries the data values. The circuit must have a fixed calculation latency between each level of flip-flops, so timing analysis can determine if the amount of logic between flip-flops can fit for the specified frequency. In this process any loops are unrolled, and you can think of this as converting the loop to a long sequence of ordinary (non-loop) statements. To do this unrolling, the synthesis tool must be able to determine the number of iterations in the loops, so it can repeated the loop body this number of times when doing loop unrolling.
In the first code example the number of iterations in the loop depends on the S_ink value, so the synthesis tool can't unroll the loop to a fixed circuit, since the circuit depends on the data value.
In the second code example the synthesis tool can determine the number of iterations in the loop, thus do the unrolling to a fixed circuit.
One way to address this is make the algorithm with a fixed number of iteration, where this number of iterations can handle the worst case input data, and where any superfluous iteration on other input data will not change the result.
Solution :
process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1;
log:=0;
for I in 1 to 14 loop
temp := temp/2;
if (temp /=0) then
log :=log+1;
end if;
end loop;
S_klog<=3*log; -- 3*log because of my application
end if;
end if;
end process;
The VHDL code below is a simple swap program. But it is not swapping the inputs a and b. I have given the transcript values in the comments.
library ieee;
use ieee.std_logic_1164.all;
entity vhdl_swap is
port(a,b: inout integer);
end vhdl_swap;
architecture ar of vhdl_swap is
signal s : std_logic;
begin
process(s)
variable var : integer:=0;
begin
report "var is" & integer'image(var); -- 0
report "a is " & integer'image(a); -- 10 - (given value when simulated)
report "b is " & integer'image(b); -- 20 - (given value when simulated)
report "---------------------------";
var := a;
report "var is " & integer'image(var);--var = 10 (assigned properly)
a<=b;
report "a is " & integer'image(a);-- a=10(same value but not assigned)
b<=var;
report "b is " & integer'image(b);-- b=20(same value but not assigned)
report "-----------------------------------";
report "a is " & integer'image(a);--a=10
report "b is " & integer'image(b);--b=20
--print()
end process;
end;
There is something which acts in the statement a<=b, but i don't know what prevents itself from assigning it.
The new value assigned with VHDL <= is not available for read until an delta delay has passed.
This is a fundamental property of VHDL, since it reflects the way register update works then the signal that triggers the update is a clock.
This also means that you can actually do the swap without a variable, but simply doing:
a <= b;
b <= a;
There are other issues with the code, e.g. what is the s used for, using a and b for both input and output will give a drive conflict, unless resolution function is added.
If you assign a new value to a signal in VHDL with <= without giving an explicit delay (with after <time>), then the new signal value will be available in the next delta cycle. A new delta cycle starts, when the simulator has suspended all processes which have been scheduled for the current delta cycle. And a process is suspended at a wait statement. Your process has an implicit wait on S; statement at the end, because you described a process with a sensitivity list containing S.
You assigned the inout ports a and b here which behave the same as a signal.
Because, the signal update is visible not until the next delta cycle, all your report statements print out the same value for a and b respectively. That is, they print out the values of a and b when the process has started / resumed.
Assigning a signal is different to assigning a variable, e.g. var in your code, which gets updated immediately.
Your process is executed only once, because the signal S is not changed. Every process is executed once after the simulation starts and then suspended at the wait statement (the implicit one in your code as described above).
You said, that a and b have the initial value of 10 and 20, respectively, but I couldn't reproduce this with ModelSim nor GHDL. I tried it with the following testbench which I think is the only possible way:
library ieee;
use ieee.std_logic_1164.all;
entity vhdl_swap_tb is
end entity vhdl_swap_tb;
architecture sim of vhdl_swap_tb is
-- component ports
signal a : integer := 10;
signal b : integer := 20;
begin -- architecture sim
-- component instantiation
DUT: entity work.vhdl_swap
port map (
a => a,
b => b);
end architecture sim;
I had to use initial values for a and b here, because both ports of mode inout and of an unresolved type. Thus, I cannot add a second driver by assigning a and b in another testbench process.
Because, the signal updates are delayed (at least) until the next delta cycle, you do not need an extra variable. Here is a very short example code demonstrating the swapping of two signals:
library ieee;
use ieee.std_logic_1164.all;
entity swap is
end entity swap;
architecture sim of swap is
signal a : integer := 10;
signal b : integer := 20;
signal clock : std_logic := '1';
begin
-- clock generation
clock <= not clock after 10 ns;
-- swapping
process(clock)
begin
if rising_edge(clock) then
a <= b;
b <= a;
end if;
end process;
end sim;
The swapping is done at every rising edge of the clock, as can be seen in the following waveform: