Can I pass a clock signal as an input argument in a Verilog task? - arguments

I was writing a testbench in VCS(G-2012.09) to verify an SPI module.
Here is a task to get a byte from a SPI master:
task get_byte;
begin
repeat(8) #(posedge spck)
begin
if (spss == 1'b0)
tmp = {tmp[6:0], mosi};
end
$display ("[Time:%dns]---->Get a byte: 0x%h", $stime, tmp);
end
endtask
It works. Then I want to parameterize this task and replace the code with:
task get_byte;
input clk, oen, din;
output [7:0] byte;
begin
byte = 8'd0;
repeat(8) #(posedge clk)
begin
if (oen == 1'b0)
byte = {byte[6:0], din};
end
$display ("[Time:%dns]---->Get a byte: 0x%h", $stime, byte);
end
endtask
But when I called the task with get_byte(spck, spss, mosi, tmp) and run the testbench in VCS, it stucked. It seemed that spck did not pass to work as clk inside this task.
So is there a rule that a clock signal can not be used as an input argument within a task or did I make anything wrong?

In one of the old stackoverflow questions you can find following answer:
In Verilog arguments are passed to tasks by value. This means that the value of clock will be fixed for the lifetime of the call to the task. Your task will never find a posedge of clock, and will wait forever.
So the answer is: you can use clk as an input argument to a task, but it won't work as "standard" clock.

You can do what you ask if you declare the task as automatic and pass the input by reference (using the ref keyword instead of the input keyword in the port definition of the task)

Use the clock without declaring it an input, as you did in the first task. Passing by reference won't work either, since the task will try to set the clock signal at the end of the task, and the simulator will throw an error.
You may want to have several tasks that reference the different clk names, i.e.:
get_byte_spclk(...)
get_byte_clk(...)

As mentioned by Qiu, this will not work.
You however can do one trick.
see the code below:
task my_task;
#(posedge testbench.name_of_the_signal_you_want_to_use_as_refernce)
Do something here
endtask
So you basically have to give path to the clock signal, something like that:
testbech.instance_of_instantiated_module.clock_signal_name

Related

Which specific signal in the sensitivity list triggers a process in VHDL

I am doing a project in VHDL and I am stuck at this point. Any help is appreciated.
The problem is described as follows:
I have a 2D array with N (in number) std_logic_vector signals. The number N is defined in generics, so we do not know the specific length of the array (we use N instead).
This array is used as sensitivity list of a process in order to trigger it. Like so: process(arrayOfSignals)
My question is: Is there any way to know which specific signal of the array triggered the process? (Like for example the signal: arrayOfSignals(2))
I have seen this post: Which signal in the sensitivity list triggers the process but it is not the case here. It would be the case if all the signals of their sensitivity list where inside an array, and this array was triggering the process.
To become clear, below is the VHDL code of what I am trying to do.
process(arrayOfSignals)
begin
for i in 0 to N-1 loop
if arrayOfSignals(i)'transaction'event then --I want to determine which signal of arrayOfSignals (position in the array) triggerd the process.
case arrayOfSignals(i) is
when "01" =>
AD(i)(30 downto 23) <= AD(i)(7 downto 0);
exit;
when others => null; exit;
end case;
exit;
end if;
end loop;
end process;
I don't know how to do exactly what you are asking. But let me suggest a way to do what I think you are trying to do.
Typically if you want to detect a change in a signal, you would have a clocked process and make a registered copy of the signal. You can then compare the state of your input signal with your registered copy (for each element) and if they are not equal, the input has changed and you can trigger your logic.

In VHDL, Can I use signal'event if signal is not a clock?

I am trying to clean up my VHDL code. I have a signal that is NOT a clk.
Can I write an event change monitor like the following and how do I get it to compile so it can be synthesized? (see code) I have tried several permutations but I cannot get it to compile. Will signal'event compile if signal is not a CLK and if so, how is it done? I see on the web and other literature that it can be done but all examples I see show CLK'event.
signal cntr: unsigned(15 downto 0) := (others => '0');
...
process(CLK):
begin
IF rising_edge(CLK) THEN
if (cntr'event) then
do something;
end if;
or...
if(cntr(0)'event) then
do something;
end if;
END IF;
end process;
I get the following and others
: can't synthesize condition that contains an isolated 'EVENT predefined attribute
rising_edge(CLK) is already an event, making your design synchronous, which is good. As said in comments, only clock signals should use that.
Looking at another even at that time doesn't make sense in synchronous designs, as the 2 signals won't change exactly at the same time, creating a race condition. Or actually a clock within a clock, and the synthesis error...
It may work in simulation, but don't rely on that fact.
The normal way to program in HDL languages is to save the previous value of the signal, on the same clock (for example cntr_d <= cntr) and to compare with that previous value. That allows to find if the signal went up (previously at 0, currently at 1), went down, changed (is different)...
And that method is perfectly fine for synthesis!

VHDL process parallelism

let's say I have two processes in my code:
prc 1 : process( CLK , RESETN ) {with some code}
Q <= outd
prc2 : process(outd,RESETN)
Note that we change outd in prc1..
A process is executed in parallel with other processes, right? how can it be executed in parallel if we dont change it's sensitivity list? in my code.. how can prc2 be executed in parallel with process 1 If I didnt change the sensitivity list of it?
And another question.. is the line Q <= outd placement has importance? doest it change anything If I put it in the last line?
The description has taken from http://www.vhdl.renerta.com:
The sensitivity list is a compact way of specifying the set of signals, events on which may resume a process. A sensitivity list is specified right after the keyword process
The sensitivity list is equivalent to the wait on statement, which is the last statement of the process statement section
So your prc2 process will wait for changing of outd or RESETN and then will start to work as many times as signals in sensitivity list will changed.
Parallelism means that all process executed in parallel. One process doesn't wait for the end of another process, but works in parallel with it. In your case: the process prc1 will work each CLK or RESETN changing and the process prc2 will work when outd or RESETN changing.
To see the picture how it works you can write (or take any example) some module and testbench for it and look at waveform how processes work.
In addition to Roman's answer, I thought I'd answer your second question:
Is the placement of the line Q <= outd important? Does it change anything if I put it in the last line?
No and no.
As long as the line Q <= outd is not inside of a process, it is purely combinational. Thus, it doesn't matter where you put it in the code - it will be synthesized into the same hardware.

VHDL - how does "reset" work and how to use?

I am new to VHDL and am trying to understand how reset operates - specifically within the Xilinx Spartan6. I've looked over this site and others, a white paper or two, but my questions do not seem to be addressed (so I fear the issue is so basic that all is assumed!)
Anyway, I inherited some example code and have made significant changes to it and succeeded in getting some decent functionality but the use of reset mystifies me.
The code looks like this:
architecture Behavioral of BigProject is
...
signal reset : std_logic := 0;
...
begin
...
reset <= '0';
...
process(clk_1MHz, reset) is
begin
if reset = '1' then
foo_flag <= '0';
fsm_a <= FSM_FIRST_STATE;
elsif rising_edge(clk_1MHz) then
case fsm_a is
when FSM_FIRST_STATE =>
<do stuff>
when FSM_SECOND_STATE =>
<do other stuff>
when others =>
null;
end case;
end if;
end process;
What does my use of reset actually accomplish?
Thanks.
With respect to the Xilinx tools, initial values on signals are honored for power-on state. For example:
signal a : std_logic := '0';
signal b : std_logic := '1';
Signal a will have a power-on reset value of '0', and signal b will have a power-on reset value of '1'.
Now, this is generally NOT the case for ASIC's, and is not the case for Microsemi parts.
Also, it is highly recommended that you limit the resets to only those bits that actually need to be reset. For example, if you have a data path that does math operations on some data in a pipeline, do you need to reset the data itself? Resets have a cost in terms of logic (depending on the logic library, it may require a multiplexer), routing (the reset has to get everywhere it is necessary), and can be complex when releasing reset.
So, limit your resets as much as possible. If an external reset is not necessary, don't use one. And if it is required, limit it's use to essential bits.
Your reset actually accomplishes nothing ;) In your code the reset is tied to '0' and thus your clocked process is always in reset state.
Usually the reset signal is an input port. So someone outside of your module asserts the reset for clock cycle or more and then releases it. After that all your registers are (or should be) in knowns states and your design is ready to do what ever it does.
edit: sorry, the reset is active high, so the tie-0 in for your reset actually makes sure that the clocked process is not reset. Ever. So every time your design starts from unknown state. That would be the red x's you see in the simulation waveform.
signal reset : std_logic := ***'0'***;
In your code the reset is tied to '0' and thus your clocked process is always in reset state.
#Jarno: That's not correct. For a synthesized module for Altera this doesn't matter ... even if there would be a 1 for the reset.
If you synthesize the code you will see that the synthesizer ignores that value. Maybe you even get a warning that the init value is ignored.
[http://quartushelp.altera.com/14.0/mergedProjects/msgs/msgs/wvrfx2_vhdl_warning_initial_value_for_signal_is_ignored.htm][1]
PS: Sorry, I am not allowed to write comments, yet.

VHDL login terminal

i am beginner in VHDL and i need do login terminal. For example i have fixed password 7010. I need implement only funcionality of automat. I want to have defined one signal, that will hold count of keys presses and will be incremented each time.
But i dont know how to initialize signal and incerement it, because when i initialize signal in one process, i cant increment its value in other process. If i dont intialize that signal, then my code not work and i dont know why. For example doSomething will not be runned if i dont that signal to "0000". But i need incerement its value in doSomething... Sry for my bad english.
if(mySignal = "0000")
doSomething
What you are trying to do sounds like a class assignment.
Break the problem down.
Draw a block diagram of what you want
In synthisisable VHDL you are correct in saying, unless the signal can be high Z, multiple drivers are not allowed. But there is nothing to stop you taking a copy of the signal and using that in another process.
Make use of unsigned types for counters or any signal that has magnitude, it makes life much easier
doSomething:process(clk,mySignal
begin
if rising_Edge(clk) then
if mySignal = "0000" then
count<=count+1;
end if;
end if;
end process;

Resources