Forum Discussion
New to VHDL: Understanding timer.vhd implementation
I'm an old hand at C/C++ just getting my feet wet with VHDL. In the course of my learning, I've used the SOPC builder to create a simplified system that included a timer. Part of the emitted VHDL code for the timer includes the following snippet:
control_wr_strobe <= (chipselect AND NOT write_n) AND to_std_logic((((std_logic_vector'("00000000000000000000000000000") & (address)) = std_logic_vector'("00000000000000000000000000000001"))));
process (clk, reset_n)
begin
if reset_n = '0' then
control_register <= std_logic'('0');
elsif clk'event and clk = '1' then
if std_logic'(control_wr_strobe) = '1' then
control_register <= writedata(0);
end if;
end if;
end process;
In simulating this with ModelSim and 'manually' driving chipselect, write_n, etc., it appears that the write into the control register by writedata(0) does not occur unless I extend the assertions of the signal lines (chipselect, write_n, address) so they last for at least two rising edges of 'clk'. My understanding is that because all of this is concurrent, on the first iteration (assuming the chipselect, write_n get asserted with the rising edge of 'clk'), ModelSim will not evaluate the "if std_logic'(control_wr_strobe) = '1' then" statement to true.. at least not on the first 'delta' iteration. This is because all of the processes and the implied process driving the value to control_wr_strobe occur at the same time. It won't be until after the delta time in the simulation following the rising edge event that control_wr_strobe will be actually evaluated to a '1'. By this time, it's too late - the rising clock edge has been evaluated and will not cause the process(clk,reset_n) to be scheduled again. Instead, it's necessary to keep chipselect & write_n asserted so that on the *next* rising clk edge the control_register is updated. Is this line of thought correct? Further, this is looking at things from a simulation mindset. When things are synthesized, is this same timing required? In other words, the chipselect and write_n lines will need to be held for at least two clock cycles to be properly executed. Does this mean that the Avalon MM Slave interface requires at least 1 wait cycle for a write? I believe this is the case, but was hoping for confirmation. Thanks! --tim7 Replies
- Altera_Forum
Honored Contributor
Understandable. I was just answering your question about why std_logic'() was being used all over the place...
I also wanted to make sure there wasn't anything I wasn't "getting" with respect to clk_en usage. Thanks for all the help! --tim - Altera_Forum
Honored Contributor
as its generated code, it is following a given template. There is nothing wrong with the code. generated code can often look at bit odd
- Altera_Forum
Honored Contributor
The code snippets I've been listing are from the VHDL code that was emitted (automatically generated) as a result of including a timer using the SOPC builder. In other words, I'm including it from Library > Peripherals > Microcontroller Peripherals > Interval Timer, generating the system, and then looking at the result as a point of reference as I delve into VHDL.
It's *that* code that is including the extra std_logic'() stuff as well as including what looks like the vacuous use of an internal signal (clk_en). --tim - Altera_Forum
Honored Contributor
I doubt it. Im guessing it was either intended to be upgraded to a real clock enable, or it was once a clock enable and found it easier to force it to one rather than removing the code the process.
I have a question for you - where are there unnessasary std_logic qualifications all over the code? clk_en <= '1'; is perfectly acceptable. You only need std_logic'() when you need to qualify something is a std_logic rather than a bit or a character. When a signal is already defined as a std_logic, there is no need to qualify its assignment. std_logic'(signal) is even more unnessasary - the signal is already a std_logic. - Altera_Forum
Honored Contributor
Thanks for the response. I've got a follow-up question regarding the timer.vhd implementation.
There is some code driven by an internal signal named "clk_en". At the beginning of the architecture, there's this:
And then later on there's this:clk_en <= std_logic'('1');
What is the purpose of checking clk_en? I'm guessing it's primarily for simulation purposes as a guard in the event that there is an immediate rising edge to prevent (in this case) force_reload from being updated with data that may not yet have a defined value. Is this the case? Thanks, --timprocess (clk, reset_n) begin if reset_n = '0' then force_reload <= std_logic'('0'); elsif clk'event and clk = '1' then if std_logic'(clk_en) = '1' then force_reload <= period_h_wr_strobe OR period_l_wr_strobe; end if; end if; end process; - Altera_Forum
Honored Contributor
I concur with josyb. It can be quite tricky at first trying to work out why a signal is changing on a clock but not acted upon until the next clock, which is why making inputs change on the falling edge can make thing a little clearer. This way they are only ever active for 1 clock edge, not 2 like you previously thought.
- Altera_Forum
Honored Contributor
Your line of thought is quite correct. If you change the input signals at the same time as clk rising, that very rising edge of the clk sees the previous values and it is only at the next rising edge of clk that the input changes will be evaluated.
I assume you are doing a functional simulation. In that case you could change the inputs at the falling edge of the clock (or at one quarter after the rising edge). Now the next rising edge will nicely evaluate all changes in one action. In real life your MM Slave will not require a wait-cycle, because the changes will be the effect of a (previously) rising clock edge.