I want to design a IIC sniffer in VHDL and I struggle at a very basic point.
To keep it "sequential" I want to set a flag after every part that will be executed by an entity.
Now I want to set a Flag on the START condition (SCL = HIGH & RISING_EDGE on SDA)
This flag should be resetted on the STOP condition (SCL = HIGH & FALLING_EDGE on SDA) and when I push a reset button.
I now have the problem that I can not get the flag to be set by the START and resetted by the STOP command.
How should I approach to get a flag for this period?
entity scltest is
port( scl, sda: in std_logic;
scled, sdaled, flag: out std_logic
);
end scltest;
architecture test of scltest is
begin
scled <= scl;
sdaled <= sda;
process(sda)
begin
if (scl = '1' AND rising_edge(sda)) then
flag <= '1';
else
if (scl = '1' AND falling_edge(sda)) then
flag <= '0';
end if;
end if;
end process;
end test;
This code does not work because:
"Error (10820): Netlist error at scltest.vhd(18): can't infer register for flag because its behavior depends on the edges of multiple distinct clocks"
I do understand why it won't work but I can't think of a design that will work which gives me the same function.
Thank you in advance.
Your basic idea seems to be that you want to do all your logic with the bus clock. However, your design shouldn't depend entirely on the bus clocks -- especially since I²C is so slow.
You'll want to have a running system that can do other tasks (like USB, USART...) to report to your host system (PC, SoC...) about the state of the I²C bus.
Towards that end, you'll need to sample both SCL and SDA and have a core clocked by your system clock perform the actual anaylsis of rising/fallig edges, bus states etc. That way, all your logic will be synchronous to your system clock.
Depending on your development board, example designs might exist that already have the host side ready and you would only need to "plug" your module in the right place. A good starting point IMHO1 would be one of Digilent's Spartan boards as the host side code is freely available with tools and a programming API.
1 I'm not affiliated with Digilent in any way.
Related
Hello everyone I wrote some VHDL code that implement a UART-TX from my FPGA to my desktop. To trigger data sending I use the signal(debounced ofc) coming from the on-board switch.
As long as the button is pressed data is being sent. Inevitably, for as quick as I can be pushing and releasing this switch, the FPGA sends many UART packet duplicates to the laptop. This is because i directly connected the button signal to the start bit of the UART-TX entity. Therefore, I removed this direct connection and instead use the button to actually generate a short bit pulse to trigger the UART-TX entity just once.
So I did this:
--start_deb is the start bit (debounced? coming from the switch
i_TX_DV_gen: process(start_deb, clk) is
variable counter: natural := 0;
begin
if rising_edge(start_deb) then
i_TX_DV <= '1';
end if;
if i_TX_DV = '1' and rising_edge(clk) then
counter := counter + 1;
if counter > 10_000 then
i_TX_DV <= '0';
counter := 0;
end if;
end if;
end process;
So the trigger bit to the UART entity is set to '1' when I press the button and then after a number of clock cycles (which I unsured smaller than the ones necessary to send one packet) it goes to '0' again avoiding the send any duplicates.
This works in simulation, I attached the waveform:
These are the signals description
clk:system clock
start_n: button signal (pressed when low)
start: not(start_n)
shift_input_n: button signal to select the next byte code.
o_TX_serial: serial output of the TX entity
packet: byte to be sent
i_TX_DV: trigger bit to start UART-TX trasmission
start_deb: start signal but debounced
The problem is that when I download it to my FPGA, the i_TX_DV is set to '1' only the first time.
[
To visualize this I used a FPGA-built-in LED, which produces a light burst every time the i_TX_DV is set to '1'( for its very short amount of time).
]
Therefore, the UART-TX entity is triggered only the first time I pressed the button. Apparently when on FPGA for some reason, i_TX_DV is not set to '1' anymore, or is set to '0' just right after.
I am using the fpga Crosslink-NX Family 8MG289C from Lattice Semiconductor.
Thank you guys, I thought of others ways to include it in a FSM and I ended up modifying the FSM of the UART-TX entity. Basically I don't go back to the idle state as long as the input start button is still pressed. This is a section of the FSM which contains the part I modified
when s_Cleanup =>
o_TX_Active <= '0';
r_TX_Done <= '1';
***if i_TX_DV = '1' then
r_SM_Main <= s_Cleanup;
else
r_SM_Main <= s_Idle;
end if;***
Anyway back at my original implementation, this was the netlist analyzer output for the pulse trigger generator:
It uses a register and a full adder to implement the counter. A register stores the value of i_TX_DV. The two multiplexer at the left are apparently used to either hold the value of the counter, updating it with the next value or "reset" it. The reset apparently is carried in this way: it comes from the d1 constant input data of bottom-left multiplexer wihch is tied to a 0. Therefore at the next clock cycle, when it holds the value it should be resetting itself. For some reason this still didn't work.
I apologize for my careless when writing the VHDL code, but when wiriting the code I just assumed that as long the simulation went well, the synthesis tool would have done the rest. Also I decided to not include too much code in order to be more coincise, because I had done several testing and made sure that all the other entities and modules were working correctly.
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!
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.
I wanted to ask if it is possible to use an inout pin as inout and normal out? The two behaviours should be switched through a MUX. The reason for this weird looking implementation is that I have two boards and I want to use the same bitstream. On one board, the same pin is connected to a LED through GPIO and on the other it goes to my I2C bus connection. The software tries to detect the I2C and if successful it sets a register. If not, it clears it.
LED_or_SDA : inout std_logic; -- port definition
process (register)
begin
if ( register = '1') then -- software sets this register
LED_or_SDA <= I2C_SDA; -- here I want to use it as inout
else
LED_or_SDA <= gpio_reg; -- here I want to use it as normal out
end if;
end process;
This implementation throws the error "bidirect pad net is driving non-buffer primitives" during translate. Is there a solution for this?
No, you can't. A mux is not a switch, it is a logic function. The line
LED_or_SDA <= I2C_SDA;
strongly drives LED_or_SDA from I2C_SDA. It does not connect the two nets in a way that allows bidirectional data flow.
You'll need to separate the two directions:
I2C_SDA_in <= LED_or_SDA;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'0' WHEN (I2C_SDA_out = '0') ELSE
'Z';
Most I2C logic blocks have separate data in and out signals anyway, right up until the external interface, where you'll find a tri-state buffer expressed in much the same way as the code I gave you. You'll simply need to make the input and output data separate ports on your I2C block.
Unfortunately, the weak drive state of the internal signal likely isn't accessible to internal logic, so these won't work:
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
I2C_SDA_out;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'Z' WHEN (I2C_SDA_out = 'Z') ELSE
I2C_SDA_out;
The VHDL compiler actually is keeping track of a tri-state control signal, and propagating that through port statements until it hits the external pin and connects it to the real (hardware) tri-state buffer. But in most compilers you can't access that control signal for your own logic.
Guessing from your error message I assume that we are talking about a Xilinx System, e.g. around a Microblaze - if that's not the case, please update your question and also specify the exact GPIO core you're using.
Often these GPIO blocks already contain the IO-Buffer macro by default. This IOBUF is located next to a physical pin and can not drive any other signals on the FPGA. Hence the GPIO block is intended to be used on the top level of the chip and be directly connected to a pin. However, there usually is a way to also access the signals before the IOBUF: E.g. in Xilinx Platform Studio on the tab "Ports" you should have a choice to use also GPIO_IO (after buffer), GPIO_IO_I (pure input), GPIO_IO_O (pure output), GPIO_IO_T (tristate) or similar.
Yes, the trick is to treat it always as a tristate buffer, and control the output based on the state of register
-- define a tristate pin the usual way.
LED_or_SDA <= LED_or_SDA_out when LED_or_SDA_tristate = '0' else 'Z';
LED_or_SDA_in <= LED_or_SDA
-- then control the data onto it, and the tristate control line
LED_or_SDA_tristate <= '0' when register = '0' else ICD_SDA;
LED_or_SDA_out <= gpio_reg when register = '0' else '0';
Let's say I have a signal, I can either assign a initial value of zero OR I can set it to zero upon RESET. I've seen my co-workers using the two method interchangeably. I just want to see others opinion on this.
Example (using initial value):
architecture arch of xxx is
signal flag : STD_LOGIC := 0;
begin
process (clk) begin
if rising_edge(clk) then
-- do something
end if;
end process;
end arch;
Example (using reset value):
architecture arch of xxx is
signal flag : STD_LOGIC;
begin
process (clk,rst) begin
if (rst = '1') then
flag <= '0';
elsif rising_edge(clk) then
-- do something
end if;
end process;
end arch;
If possible, use a dedicated reset signal, for several reasons:
Designs using complex clock generation may require that a module is held idle
(reset) until the clock is stable. Using initial values with an unstable but
running clock may change the initial value from the expected.
A module that interfaces to other or external modules may get protocol
violations on an interface during startup, and to avoid wrong operation or
hangup due to protocol violations, it may be required to hold the module in
reset until the protocol operation is well defined in the interface.
Restart of the entire system, or part of the system, is possible by asserting
reset, instead of having to reload the entire FPGA, which takes much longer
time, and may be more complicated if it requires CPU interaction.
Some FPGA technologies, for example Altera partial reconfiguration, does not
support initial values for the modules used in partial reconfiguration.
Reuse of modules is therefore easier if only reset is used.
Simulation of different start/restart conditions is easier when it is
possible to apply reset, and continue the same simulation sequence. If
initial value is used, then the entire simulation must be restarted.
Apply reset to as few flip-flops as possible, for the resource reasons that Russell
points out. Also, applying it to only the required flip-flop, makes it easier
to catch bugs and oversights in the design during simulation, since unknown X
values may then appear. The reset should be asynchronous, since most FPGA and
ASIC technologies have flip-flops with dedicated reset input, and the reset
will then not slow down the timing of the synchronous design part, by insertion of logic to apply a reset value. The slow down can be seen in for example Altera Cyclone V, where logic is inserted in the data path due to the synchronous reset through a MLABCELL, as shown in the data path timing report here:
A flip-flop using asynchronous reset does not have this extra delay in the data path, as can be seen in figure through this link.
The process for flip-flops with reset should be written with the reset part as:
process (clk, rst) begin
if rising_edge(clk) then
-- Flip-flops updated at clock
end if;
if (rst = '1') then
-- Flip-flops reset
end if;
end process;
This coding style makes it possible to apply reset to only some of the
flip-flops updated at the rising clock, while the remaining flip-flops are
implemented without reset.
The combined if-then-elsif-end if in question code, actually specified that
the state is held during reset for flip-flops that are not reset, since the
rising_edge(clk) part of the if does then not take effect. This is
probably not the intended implementation.
For proper timing, the reset signal (rst) should be synchronized to the clock
(clk), at least for deassertion (1 to 0), so recovery and removal time are not violated.
'Value after FPGA configuration' vs 'Value after reset'
The initial value will be the value the signal will get after the FPGA configuration.
The value affected in case of a reset will be... the value the signal will get in case the reset signal is asserted :-)
About the signal value after FPGA configuration
From Xilinx "Large FPGA Methodology Guide" page 31 :
FPGA devices have dedicated global set/reset signals (GSR). At the end of device
configuration, the GSR is automatically asserted to initialize all registers to the initial state specified in the HDL code.
Every register is at a known state at the end of configuration. You do not need to code a global reset for the sole purpose of initializing the device.
Of course, you need to trust the FPGA you use about this initial value. People often prefer to have a reset on control signals to ensure this out of configuration initial value, even if this is normaly not required...
To reset or not to reset
Maybe you need a reset for specific other reasons :
coding rules that enforce this
the necessity to set this signal back to a known value without having to reconfigure the FPGA
If you need this reset, it will probably be asserted when the FPGA go out of configuration, and the initial value will then be useless, so it is probably better to not use it.
Hope this helps.
I'm of the opinion that you should not reset any signals that do not need it. Only things like state machines or counters should be reset. Adding resets to everything means that the tools will have to add routing resources to hook up all of these resets. So for example I almost never reset any signal that just holds data, or some enable signal that will only be active for one clock cycle anyway.
Regarding initialization, I initialize every register that I infer. This can be easily checked by looking at a modelsim waveform. Red = Bad. This takes no additional resources to achieve, but it ensures that the FPGA starts up in a known-condition.