I have the following problem:
I have a simple entity driven by a single process:
LIBRARY IEEE;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_arith.ALL;
entity somma_CDC is
Port
(
A : in std_logic;
B : in std_logic;
Reset : in std_logic;
Internal_Carry_enable : in std_logic;
S : out std_logic
);
end somma_CDC;
architecture Behavioral_somma_CDC of somma_CDC is
signal Internal_Carry: std_logic;
begin
somma_CDC:process (Reset,A,B)
begin
if Reset = '1'
then
Internal_Carry <= '0';
else
S <= A XOR B XOR Internal_Carry ;
if (Internal_Carry_enable = '1')
then
Internal_Carry <= (A AND B) OR (Internal_Carry AND A) OR (Internal_Carry AND B) ;
end if;
end if;
end process;
end architecture;
In practice, it is very similar to a full adder.
Ideally, the block diagram should look like this:
My problem arises when in the cycles following the first, I find the values of the operands equal. In this case, the process does not activate and therefore fails to calculate the case in which
A = 1, B = 1, Carry_In = 1.
There is a clock signal in my system, but the clock goes faster than the input data change. If I put the clock in the sensitivity list I get wrong results, as the carry "propagates" in the wrong way.
I tried without using the sensitivity list and putting a wait for "X" time, with "X" the minimum time for changing operands A and B. It works, but it depends on something that can always change in a project.
Is there another way to activate this process?
TL;DR:
Add Internal_Carry to your sensitivity list.
Edit: As #Tricky pointed out, Internal_Carry_enable should be in the sensitivity list as well.
Full Answer:
I think the problem here is that you may miss understood how to use the sensitivity list. You are using it as C like programming, where the process would be reading reset, A and B as inputs.
But in vhdl every signal in the sensitivity list is a trigger that must change its value in order for the process to be rerun again.
So, the main problem here is the signal Internal_Carry. Since it is not in the sensitivity list, the signal S wont respond as Internal_Carry change to a new value after the first run. You would need to change either reset, A or B to see the effects of Internal_Carry from the last run.
There are other problems in your code, but not related to this.
Internal_Carry is a latch since you didnt assign any default value to it (which value should it holds if reset is not 0 and Internal_Carry_enable is not 1?).
You may need to take a look in the differences between combinational and sequential logic, since you wrote about clock in an adder circuit. If you add a clock the assignment of a value to a signal will generate a register, while a process without a clock in its sensitivity list will be purely combinational.
Related
I created the following Counter with a compare match functionality:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity Counter is
generic (
N : natural := 24
);
port (
-- Input counter clock
clk : in std_logic := '0';
-- Enable the counter
enable : in std_logic := '0';
-- Preload value loaded when clk is rising and load is 1
load_value : in std_logic_vector((N-1) downto 0) := (others => '0');
-- Set to 1 to load a value
load : in std_logic := '0';
-- Compare match input is compared with the counter value
compare_match_value : in std_logic_vector((N-1) downto 0) := (others => '0');
-- Is 1 when compare_match_value = counter_value
compare_match : out std_logic := '0';
output_value : out std_logic_vector((N-1) downto 0) := (others => '0')
);
end Counter;
architecture Behavioral of Counter is
signal counter_value : unsigned((N - 1) downto 0) := to_unsigned(0, N);
begin
output_value <= std_logic_vector(counter_value);
process (clk) is
begin
if rising_edge(clk) then
if enable = '1' then
if load = '1' then
counter_value <= unsigned(load_value);
else
counter_value <= counter_value + 1;
end if;
else
if load = '1' then
counter_value <= unsigned(load_value);
end if;
end if;
end if;
end process;
process (counter_value) is
begin
if unsigned(compare_match_value) = counter_value then
compare_match <= '1';
else
compare_match <= '0';
end if;
end process;
end Behavioral;
The behavior of my counter is to be fully synchronous with the input clk signal. Disabling the counter is always possible and the value is held at the current count value. A load value can be assigned with the load and load_value signal. Whenever the load signal is high and a rising edge is detected, the counter value is updated to the load_value.
Another feature is the compare unit which outputs high on compare_match output. The simulation works as expected but I have a few questions when synthesizing this design on spartan 3 fpga.
Is this considered a good design of my counter because I'm still not much experienced in VHDL.
Are there any undefined states when using the compare unit in further logic in my design? As I see it compare_match is calculated whenever the counter_value is updated.
When using a large number for N, is there anything special about the delay I need to consider?
In general it seems to me a quite good description.
However, I would like to point out some minor things (that might me some answers to your 1st question).
1) As, I see right now your counter does not contain any reset (neither asynchronous nor synchronous). In general you cannot predict the starting point of your counting (even if, probably, it will be all '0's at start-up).
In my opinion, it would be a neater design if you could have a reset signal.
I also noticed that the loading is activated regardless of the fact that the counter is enabled or not. I have no comment about this since it could be a specification for your design. Maybe you can compact the code by moving the "if load" part outside of the "if enable" (i.e. changing the order to the comparisons).
To improve the readability (especially when the designs will be more complex), I advise you to label the process. This will help you to identify the different part of the design.
You can skip lot of the extra-typing if you use the VHDL-mode of emacs. It has built in templates that would take care of the "boring" part related to coding.
I also see that you have default values for your input ports. In my opinion, this is not a very good practice; they would be ignored by synthesizer leading to an IP that might behave differently than what you expect. In general, do not make assumptions (a part those that are specified) on the external signals.
Finally, I have a comment about the compare part.
This goes for both question 1) & 2)
1-2)
In the compare process, you have just listed counter_value in the sensitivity-list.
This means that the process would be activated only when counter_value changes.
Since you compare it with a signal (compare_match_value) that is an input to the block (hence it can change values) it would be better to have it too in the sensitivity-list. Otherwise, the comparison would not apply (i.e. the process would not be activated) when you change compare_match_value.
Linting tools and synthesizer might complain about it (stating warning like incomplete sensitivity-list). As matter of fact it is good practice to list all the signals that may change in the list for combinatorial processes.
Regarding the comparison itself, the way you described it is absolutely fine and you would not have uncovered states. Basically you have specified all possible conditions so no surprises there.
3)
Regarding your 3rd question, since you are targeting an FPGA, you could "relax" about it. FPGAs have dedicated structure for fast arithmetic operations and (as long as you do not use all of them) the synthesizer would use them to close time.
Also in ASIC, synthesizer would probably select an appropriate arithmetic structure to close time.
If you want to be on the safe side, you can add a register at the output of the comparison block. This will prevent creating a long combinatorial path especially if you IP has to be integrated with other blocks. Of course this extra-register would add an 1-clock-cycle latenc, but it will improve your overall timing.
I hope these suggestions could be useful to you and cover (at least partially) your doubts.
Keep on coding :)
My project is design of 32bit MAC(Multiply and Accumlate) unit using reversible logic. For the project , i have designed 32bit mulitplier and 64 bit adder using reversible logic. Now, in the next step i want to design a 64 bit accumlator which takes the value from the adder and stores it and adds with the previous value present in it. I am not getting any idea how to design Accumlator.
Please help in completion of my project.
A basic VHDL accumulator can be implemented in only a few lines of code. How you decide to implement it, and any additional features necessary are going to depend on your specific requirements.
For example:
Are the inputs signed or unsigned?
What is the type of the inputs?
Does the accumulator saturate, or will it roll over?
Here is a sample unsigned accumulator to give you an idea of what you need to implement (based on this source):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity accumulator is
port (
DIN: in std_logic_vector(3 downto 0);
CLK: in std_logic;
RST: in std_logic;
DOUT: out std_logic_vector(3 downto 0)
);
end entity accumulator;
architecture behave of accumulator is
signal acc_value : std_logic_vector(3 downto 0);
begin
process(CLK)
begin
if rising_edge(CLK) then
if RST='1' then
acc_value <= (others => '0'); -- reset accumulated value to 0
else
acc_value <= std_logic_vector( unsigned(acc_value) + unsigned(DIN) );
end if;
end if;
end process;
-- Assign output
DOUT <= acc_value;
end behave;
To describe what this design does in words: Every clock cycle on the rising edge, the data input DIN is interpreted as an unsigned value, and added to the currently accumulated value acc_value. If the RST input is asserted, instead of accumulating the DIN input, the accumulated value is cleared back to 0. The value of the accumulator is always presented on the output of the block, DOUT.
Based on what you are interfacing with, you might want to consider the following changes/modifications:
Perhaps DIN should be signed or unsigned types instead of std_logic_vector. I actually recommend this, but it depends on how you are representing your values in other places of your design.
DOUT could also be a signed or unsigned value instead of std_logic_vector - it depends your requirements.
In this case, acc_value, the accumulated value register, will rollover if the values accumulated get too high. Maybe you want to generate an error condition when this happens, or perform a check to ensure that you saturate at the maximum value of acc_value instead.
acc_value need not be the same width as DIN -- it could be twice as wide (or whatever your requirements are). The wider it is, the more you can accumulate before the rollover condition occurs.
I have a question on VHDL. The code below is for a +/- 2 degree thermostat it works and simulates well, but I have a few unexplained warnings one of them in particular is really bugging me.
LIBRARY IEEE;
USE IEEE.std_logic_1164.all, IEEE.std_logic_arith.all;
ENTITY thermo IS
PORT (
Tset, Tact: in integer;
Heaton: out std_logic
);
END ENTITY thermo;
ARCHITECTURE sequential OF thermo IS
BEGIN
PROCESS (Tact, Tset) IS
VARIABLE ONOFF: std_logic;
BEGIN
IF Tact <= (Tset - 2) then
ONOFF := '1';
ELSIF Tact >= (Tset + 2) then
ONOFF := '0';
ELSE ONOFF := ONOFF;
END IF;
Heaton <= ONOFF;
END PROCESS;
END ARCHITECTURE sequential;
The warning message thats bugging me is this:
Warning (10631): VHDL Process Statement warning at thermo.vhd(19): inferring latch(es) for signal or variable "ONOFF", which holds its previous value in one or more paths through the process<
Like I said the code works ok on ModelSim but this makes me think i am going about things the wrong way. Any suggestions ?
Thanks
Danny J
The process is specified to hold the current value of ONOFF with the line:
ELSE ONOFF := ONOFF;
Holding the value based on combinatorial inputs, like Tact and Tset, requires a latch, as reported in the warning, since usually latches means that the designer created code with an unintentional side effect.
If you want to keep the state, then consider making a clocked process instead; a template is provided in this answer.
If you want a combinatorial output, then get ridge of the internal ONOFF process variable, and make sure that an explicit value is assigned in all branches of the if statement.
You have described a SR latch for the signal ONOFF. This works fine in simulation but makes problems in FPGAs as well as digital circuits build from discrete components.
Your latch is set when the expression Tact <= (Tset - 2) is true. Now image a point in time, when the latch is currently in state '0' and Tact = Tset. Thus, the latch keps '0' as expected. This works as long as Tact is not changing. Now let the temperature fall to Tact = Tset-1. According to the above expression, the latch should keep in state '0'. But, this cannot be ensured in real hardware because the expression is not evaluated at once. Instead the multi-bit comparator for the <= operator may produce a glitch because the comparator itself is composed of several gates. If one of these gates is switching faster than another one, there might be an intermediate result, where the expression is true and, thus, your latch becomes '1'.
To notify the designer, that latches are susceptible for glitches, the synthesis compiler issues the above warning. To circumvent this problem, the FPGA offers D flip-flops which state is only updated on clock-edges. The timing analyzer of the FPGA toolchain ensures, that the evaluation of the above expression is completed before the next rising (or falling) clock-edge. So, the designer has not to worry about glitches!
You can describe a clock-edge triggered SR flip-flop in VHDL which is then mapped to the D flip-flop of the FPGA by the synthesis tool. The code style is as follows:
signal Q : std_logic; -- declare signal in the declarations part of the architecture
...
process(clock)
begin
if rising_edge(clock) then -- flip-flop triggered at the rising clock edge
if set_expression then
Q <= '1';
elsif reset_expression then
Q <= '0';
end if;
end if;
end if;
The state of the SR flip-flop is saved in the signal Q. I have used a signal instead of an variable here, because variables are harder to debug. (I recommend to use signals as often as possible.) In this code example, if both set_expression and reset_expression are both true, then the "set" takes precedence. (Can be flipped if required.) If none of the expressions is true, then the old state is saved as required by a flip-flop.
The code below is a simple vhdl structural architecture, however, the
concurrent assignment to the signal, comb1, is upsetting the simulation
with the outputs (tb_lfsr_out) and comb1 becoming undefined. Please, please help,
thank you, Louise.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity testbench is
end testbench;
architecture behavioural of testbench is
CONSTANT clock_frequency : REAL := 1.0e9;
CONSTANT clock_period : REAL := (1.0/clock_frequency)/2.0;
signal tb_master_clk, comb1: STD_LOGIC := '0';
signal tb_lfsr_out : std_logic_vector(2 DOWNTO 0) := "111";
component dff
port
(
q: out STD_LOGIC;
d, clk: in STD_LOGIC
);
end component;
begin
-- Clock/Start Conversion Generator
tb_master_clk <= (NOT tb_master_clk) AFTER (1 SEC * clock_period);
comb1 <= tb_lfsr_out(0) xor tb_lfsr_out(2);
dff6: dff port map (tb_lfsr_out(2), tb_lfsr_out(1), tb_master_clk);
dff7: dff port map (tb_lfsr_out(1), tb_lfsr_out(0), tb_master_clk);
dff8: dff port map (tb_lfsr_out(0), comb1, tb_master_clk);
end behavioural;
It's just a little more complex than Radix Ciano(1) says. All tb_lfsr_out elements are showing 'U' from Now = 0 ns. The reason why is that all of the D flip flops aren't initialized.
All tb_lfsr_out elements are showing 'U' from Now = 0 ns. The reason why is that all of the D flip flops aren't initialized.
If you reset all the flip flops the result will always be '0' without a '1' to cause a flip in the XOR gate.
Preset the D flip flops (which can come for free in an FPGA implementation):
This was done by simply adding a default value:
q: out std_logic := '1';
(1) Yes it's a minor change, and to all appearances someone changed their user name and if asked I would have changed Radix to Ciano. Making changes simply to cross a threshold is ridiculous.
The entire purpose of this answer was to avoid stepping on the other answerer's rights of authorship and now he's done the very thing. The issue with his answer being that the complimentary property of XOR prevented the LFSR from working when all inputs were '0's or any inputs were metavalues.
And while you're at it no one noticed the error in the waveform now corrected, apparently too self absorbed in playing games with answer edits. (The signals after the label dff8 were actually from dff7).
There's a message here which is in the form of a question. What's the purpose in answering questions on stackoverflow? See Why I no longer contribute to StackOverflow . And note Mr. Richter's reputation has continued to eek upward, including for the example post on goto he cites as likely to induce severe ire. (And the message there is have patience all you petty editors, sooner or later you're 'reputation' will reach self sustaining levels unless the system is altered to prevent it).
Also note the question's author has to date and after an impassioned plea closing his question not show acceptance of nor use for any answer.
In the mean time quit spoiling why I answer questions on VHDL by changing the words I write, although I have to admit the edit voting history was entertaining.
My question is in regards to the following code:
library ieee;
use ieee.std_logic_1164.all;
entity exam is port (
I,CLK,RESET : in std_logic;
Q : out std_logic
);
end entity;
architecture exam_arc of exam is
signal temp_sig : std_logic;
begin
process (CLK,RESET)
begin
if RESET = '1' then
temp_sig <='0';
elsif CLK'event and CLK='1' then
temp_sig <= I;
end if;
Q <= temp_sig;
end process;
end exam_arc;
It seems that this piece of code simulates a D flip flop that operates on rising edge of the clock, however the answer [this question is taken from an exam] to this question claims that this D flip flop operates on falling edge of the clock.
What kind of flip flop this VHDL code simulates?
It's a trick question. Note that the process wakes up on both rising and falling clock edges, and that the intermediate signal temp_sig is assigned on the rising_edge.
Put that together with the semantics of signal assignment (postponed assignment) and see what you get.
Cross check via simulation as Jim suggests...
Separate the assignment to Q into it's own process statement with the same sensitivity list. The simulation models behavior will be identical although they vary in the number of processes.
DUT:
process (CLK,RESET)
begin
if RESET = '1' then
temp_sig <='0';
elsif CLK'event and CLK ='1' then
temp_sig <= I;
end if;
-- Q <= temp_sig;
end process;
QDEVICE:
process (CLK, RESET)
begin
Q <= temp_sig;
end process;
The edge sensitive storage device assigning temp_sig is clearly a positive edge clocked flip flop sensitive to CLK and asynchronously reset by RESET (high).
Is the QDEVICE process a synthesis target construct? It behaves as a follower latch to the temp_sig flip flop, but there is no indication as to the polarity of an enable. See IEEE Std 1076.6-2004 IEEE Standard for VHDL Register
Transfer Level (RTL) Synthesis, 6.2.1.1 Level-sensitive storage from process with sensitivity list:
A level-sensitive storage element shall be modeled for a signal (or variable) when all the following apply:
c) There are executions of the process that do not execute an explicit
assignment (via an assignment statement) to the signal (or variable).
Without qualification (by level) rule c is not met. Further in the original process you cite the behavior doesn't map to one of the IEEE Std 1076.6-2004 6.2 Clock edge specifications none of which include using an intermediary signal.
Brian is right it's a trick question. A flip flop with a follower-something-else providing delay. And the 'U' value in the simulation for q until an event on CLK or RESET should be telling.
You could just synthesize it yourself.
See also ffv3 http://www.cs.uregina.ca/Links/class-info/301/register/lecture.html which is almost the same.
Update
I was missguided by the missing formatting – in fact it actually is toggling on the falling edge as another answer already shows.
Although all asignments are done in sequence, signal assignments still happen at the end of the process, and thus temp_signal is half a clock cycle old (next falling edge) and does not contain the recently asigned value.
http://www.gmvhdl.com/process.htm
How does signal assignment work in a process?
Have you simulated it? When does Q change and why? When do signals update? During a rising edge, does Q get the value of I? Make sure to simulate it.
Lets look at the following line of code:
elsif CLK'event and CLK='1' then
CLK is your timing signal (aka the clock).
CLK'event is triggered when there is a change in the value of CLK.
CLK='1' means that the clock is equal to high.
So if the clock has changed and it is currently in the high state then we will execute the code within this ELSIF statement.
We know that there are only 2 states for bit variables, so if CLK changed AND it changed to a high state then it was originally in a low state. This means that the code will only execute when the clock goes from low to high.
If you wanted to execute on a high to low trigger then you would change the statement to read like this:
elsif CLK'event and CLK='0' then