cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Visitor
Visitor
12,558 Views
Registered: ‎03-04-2014

I2C Controller Without Using Processors

Hi,

I need a I2C Core to control serial eeprom's. In most of the I2C examples on the web, microprocessors are used. But I want use only FPGA. How can i do that? and Does anyone have I2C controller which doesn't require processor or microcontroller?

Thanks.

Tags (2)
0 Kudos
Reply
24 Replies
Professor
Professor
12,543 Views
Registered: ‎08-14-2007

What exactly do you want to do with the serial EEPROM's?  It's not clear what you mean by "control" serial EEPROM's, since normally you'd just eithe read or write data to them.

 

In essence, the I2C protocol itself is fairly simple.  So without a processor, how you set about designing an interface to I2C depends on what exactly you want to accomplish.  There is code available on opencores for this (haven't tried it myself so I won't rate its usefulness).  I have written code for dealing with simple I2C slaves with 7-bit I2C address and no more than 1 address byte (like a 2Kbit EEPROM, and typical of I/O expanders and video devices that use I2C for setup of internal registers).

-- Gabor
Historian
Historian
12,535 Views
Registered: ‎02-25-2008


@fatihdag wrote:

Hi,

I need a I2C Core to control serial eeprom's. In most of the I2C examples on the web, microprocessors are used. But I want use only FPGA. How can i do that? and Does anyone have I2C controller which doesn't require processor or microcontroller?

Thanks.


I would start with the I2C spec, available from the NXP web site.

Since your master is dealing only with known slaves, it greatly simplifies the problem. You don't need to worry about multi-master arbitration, and you probably don't have to deal with wait states. 

Basically, it boils down to a state machine and a couple of shift registers.

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
12,503 Views
Registered: ‎03-04-2014

First of all thank you for your interest.

Firstly I just want to write one byte data to an eeprom until getting the experience. Most of the examples from opencores includes mp or wishbone controller signal. It comes more complicated to me. I couldn't write my own i2c codes at the moment. So I try the work on existed codes. I'have worked i2c theory. Also I studied on the datasheet of the eeprom. I just want to send totally 35 bits (start-device type identifier-ack-byte adress-ack-data byte-ack-stop) with i2c protocol. 

Thanks.

0 Kudos
Reply
Teacher
Teacher
12,490 Views
Registered: ‎03-31-2012

look at this directory: http://www.fpga4fun.com/I2C.html

it has a simple i2c code which you can use to implement an i2c controller and connect it to chipscope vio to do reads/writes manually.
- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
Visitor
Visitor
12,396 Views
Registered: ‎03-04-2014

Thanks for your interest. I found a video about the i2c master. It could be helpfull for the beginners like me.

 

http://www.youtube.com/watch?v=skkyudHHSWY

0 Kudos
Reply
Visitor
Visitor
12,346 Views
Registered: ‎12-10-2013

Dear all,

 

I fairly new to fpgas and for learning porpuses I am developing a I2C Module in VHDL.

 

I am having trouble with the i2c clock because it is not in phase with a signal that I created and I don't know why.

 

I will put the code in here as well as a screenshot of the ISim wave in hope that someone could give a hint on what I am doing wrong. I know that the module is not ready..

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity i2c is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           i2c_sda : out  STD_LOGIC;
           i2c_scl : out  STD_LOGIC);
end i2c;

architecture Behavioral of i2c is
	
	
	constant IDLE : std_logic_vector :="000";
	constant START : std_logic_vector :="001";
	constant ADDRESS :  std_logic_vector :="010";
	constant RW :  std_logic_vector :="011";
	constant ACK :  std_logic_vector :="100";
	constant DATA :  std_logic_vector :="101";
	constant ACK2 :  std_logic_vector :="110";
	constant STOP :  std_logic_vector :="111";
	
	signal addr: std_logic_vector (6 downto 0) := (others => '0');
	signal dat: std_logic_vector (6 downto 0) := (others => '0');
	signal i2c_scl_signal: std_logic;
	
	signal state: std_logic_vector (2 downto 0);


begin

	I2C: Process(clk)
	
	variable Counter : integer range 0 to 7;
	
	begin
	
		
		
		if falling_edge(clk) then
			if reset = '1' then
				i2c_scl_signal <= '1';
				
			elsif state = IDLE or state = START or state = STOP then
				i2c_scl_signal <= '1';
								
			else
				i2c_scl_signal <= not i2c_scl_signal;
				i2c_scl <= i2c_scl_signal;
			end if;
		end if;
	
		if rising_edge(clk) then
			if reset = '1' then
				state <= IDLE;
				i2c_sda <= '1';
				i2c_scl <= '1';
				addr <= "0110000";
				dat <= "0011100";
				Counter := 0;
			end if;
			
			case state is
			
				when IDLE =>
					i2c_sda <= '1';
					state <= START;
				
				when START =>
					i2c_sda <= '0';
					state <= ADDRESS;
					Counter := 6;
					
				when ADDRESS =>
					i2c_sda <= addr(Counter);
					if Counter = 0 then state <= RW;
					else Counter := Counter -1;
					end if;
					
				when RW =>
					i2c_sda <= '1';
					state <= ACK;
					
				when ACK =>
					state <= DATA;
					Counter := 7;
					
				when DATA =>
					i2c_sda <= dat(Counter);
					if Counter = 0 then state <= ACK2;
					else Counter := Counter - 1;
					end if;
					
				when ACK2 =>
					state <= STOP;
					
				when STOP =>
					i2c_sda <= '1';	
					state <= IDLE;		

				when others => state <= IDLE;
					
			
			end case;
			
		end if;
	end Process I2C;


end Behavioral;

 i2c_clock.jpg

 

To be more specific, when I enter in the Address state, at the falling edge of the clock, both i2c_scl and i2c_scl_signal should go from 1 to 0 (where the yellow mark is) but the signal does that and the i2c_scl doesn't. This last wave waits one period to go from 1 to 0..why? I put some of the code in bold to be easier for you to track the problem.

 

Thank you in advance for your help!

0 Kudos
Reply
Xilinx Employee
Xilinx Employee
12,343 Views
Registered: ‎01-03-2008

> both i2c_scl and i2c_scl_signal should go from 1 to 0 (

 

You are using a non-blocking assigments so this will i2c_scl will always be one falling edge clock cycle behind i2c_scl_signal (if you didn't want this then why did you write it this way).  Except for when it runs into a contention with a reset in the rising_edge.

 

You need to use a single clock edge in your design as the code that you wrote is not synthesizable.

------Have you tried typing your question into Google? If not you should before posting.
Too many results? Try adding site:www.xilinx.com
0 Kudos
Reply
Visitor
Visitor
12,336 Views
Registered: ‎12-10-2013

>You are using a non-blocking assigments so this will i2c_scl will always be one falling edge clock cycle behind i2c_scl_signal (if you didn't want this then why did you write it this way).  Except for when it runs into a contention with a reset in the rising_edge.

 

Well I didn't do it on purpose. After reading your post I read about blocking and non-blocking assigments. As far as I understood, and please correct me if I am wrong, signals are assigned using "<=", and they are always non-blocking and variables, for instance, are assigned using ":=" this assignment is blocking. As I am trying to use the same signal twice on the same clock edge, one of the assignments will be done one clock later.

 

So, so solve this I believe that could set the i2c_scl_signal as variable instead of signal however ISim doesn't allow to plot variables, useful for debugging. There is any alternative solution or I really have to use variables in this case?

 

>You need to use a single clock edge in your design as the code that you wrote is not synthesizable.

Didn't know that. You mean never or for any specific reason in my code? What for instance if I were using rising_edge(clk) and falling_edge(clk2)...different clocks..is this valid?

0 Kudos
Reply
Historian
Historian
12,329 Views
Registered: ‎02-25-2008


nnunes wrote:

Didn't know that. You mean never or for any specific reason in my code? What for instance if I were using rising_edge(clk) and falling_edge(clk2)...different clocks..is this valid?


The real reason your code is not synthesizable is because you assign to i2c_scl in two processes, the rising edge and the falling edge.

 

I don't understand why you feel the need to use the falling-edge logic at all. While it is certainly legal to clock stuff on whichever edge of the clock, in generally you just pick one edge. There is no advantage to clocking something on the rising edge and having the following flop clock the first flop's output on the falling edge. That just cuts your max period in half.

 

Anyways, a much larger problem is that you've got i2c_sda declared in the port list as an output. It must be a bidirectional; a slave acknowledges a byte transfer by pulling down sda. A slave can't do that with the master always driving.

 

As for the blocking (variable) vs non-blocking (signal) assignment, in general unless you have a Real Good Reason you use signal assignments.

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Xilinx Employee
Xilinx Employee
10,732 Views
Registered: ‎01-03-2008

The ":=" is a VHDL construct and in Verilog the "=" is a block assignment.  If you wrote:

 

 i2c_scl_signal = not i2c_scl_signal;

 i2c_scl        = i2c_scl_signal;

 

it would be the same as writing:

 

 i2c_scl_signal <= not i2c_scl_signal;

 i2c_scl        <= not i2c_scl_signal

 

This page has a decent example on the use of blocking vs non-blocking.

 

> You mean never or for any specific reason in my code?

 

I meant never.   You can write a process and use the positive edge of a clock and you can write a process and use the negative edge of a clock and these will synthesis to a register with or without an invertor on the clock pin, but there is no resource in the FPGA that supports both negative and postive clocks.  This isn't just a FPGA limitation, you also won't find a dual edge register in an ASIC or your digital circuit books.

 

Note: There is a resource in the FPGA that behaves as a dual-edge register and this is the ODDR  for the DDR I/O's.  While this looks like a dual-edge register in reality there are two registers with one on the positive edge and one on the negative edge and the clock level is used for a mux select to determine which will be sent to the output.  Synthesizer will not infer these blocks and they must be instantiated in the code.

 

------Have you tried typing your question into Google? If not you should before posting.
Too many results? Try adding site:www.xilinx.com
0 Kudos
Reply
Visitor
Visitor
10,713 Views
Registered: ‎12-10-2013


@bassman59 wrote:

The real reason your code is not synthesizable is because you assign to i2c_scl in two processes, the rising edge and the falling edge.

 

I don't understand why you feel the need to use the falling-edge logic at all. While it is certainly legal to clock stuff on whichever edge of the clock, in generally you just pick one edge. There is no advantage to clocking something on the rising edge and having the following flop clock the first flop's output on the falling edge. That just cuts your max period in half.


 

Well, I'll try to explain why I did it. Look for instance at the i2c start condition: It is expected to have the scl high and sda on falling edge..it was pretty much these situations that I was trying to achieve. Can I do the start of i2c if scl is on its rising edge and sda on its falling edge?


@bassman59 wrote:

Anyways, a much larger problem is that you've got i2c_sda declared in the port list as an output. It must be a bidirectional; a slave acknowledges a byte transfer by pulling down sda. A slave can't do that with the master always driving.


Oh you're right! Thank you for pointing that out. I'll correct it.

 


@mcgett wrote:

@the ":=" is a VHDL construct and in Verilog the "=" is a block assignment.  If you wrote:

 

 i2c_scl_signal = not i2c_scl_signal;

 i2c_scl        = i2c_scl_signal;

 

it would be the same as writing:

 

 i2c_scl_signal <= not i2c_scl_signal;

 i2c_scl        <= not i2c_scl_signal

 

This page has a decent example on the use of blocking vs non-blocking.


 

Understood. I really wasn't aware of the existance of blocking and non-blocking assignments. The link you posted was also useful to understand the concept.

 


@mcgett wrote:

 

I meant never.   You can write a process and use the positive edge of a clock and you can write a process and use the negative edge of a clock and these will synthesis to a register with or without an invertor on the clock pin, but there is no resource in the FPGA that supports both negative and postive clocks.  This isn't just a FPGA limitation, you also won't find a dual edge register in an ASIC or your digital circuit books.

 

Note: There is a resource in the FPGA that behaves as a dual-edge register and this is the ODDR  for the DDR I/O's.  While this looks like a dual-edge register in reality there are two registers with one on the positive edge and one on the negative edge and the clock level is used for a mux select to determine which will be sent to the output.  Synthesizer will not infer these blocks and they must be instantiated in the code.

 


Ok didn't knew that either. Shouldn't ISE give me an error when I try to Synthesize the code I posted before?

 

0 Kudos
Reply
Xilinx Employee
Xilinx Employee
10,708 Views
Registered: ‎01-03-2008

> Shouldn't ISE give me an error when I try to Synthesize the code I posted before?

 

Yes, it should result in an ERROR condition.

------Have you tried typing your question into Google? If not you should before posting.
Too many results? Try adding site:www.xilinx.com
0 Kudos
Reply
Historian
Historian
10,704 Views
Registered: ‎02-25-2008


@nnunes wrote:

Well, I'll try to explain why I did it. Look for instance at the i2c start condition: It is expected to have the scl high and sda on falling edge..it was pretty much these situations that I was trying to achieve. Can I do the start of i2c if scl is on its rising edge and sda on its falling edge?


You have a high-speed FPGA clock to which everything is synchronous. Say it's 50 MHz. It's easy enough to assert the START and other I2C bus states when your timing granularity is 20 ns!

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
10,700 Views
Registered: ‎12-10-2013


@mcgett wrote:

> Shouldn't ISE give me an error when I try to Synthesize the code I posted before?

 

Yes, it should result in an ERROR condition.


It doesn't. I got some warnings but I believe that they are not related with the rising/falling edge because I putted all in the rising edge and the warning are the same.

0 Kudos
Reply
Xilinx Employee
Xilinx Employee
10,697 Views
Registered: ‎01-03-2008

Did you take it place and route? At the very least I would expect that you get a multi-source error.

------Have you tried typing your question into Google? If not you should before posting.
Too many results? Try adding site:www.xilinx.com
0 Kudos
Reply
Visitor
Visitor
10,667 Views
Registered: ‎12-10-2013


@mcgett wrote:

Did you take it place and route? At the very least I would expect that you get a multi-source error.


I hadn't but now I did and I'm still not getting any error.

0 Kudos
Reply
Visitor
Visitor
10,453 Views
Registered: ‎12-10-2013

Hello again :) ,

 

I'm trying not to bore you too much but I need your help again.

 

I am trying to push this to a new level and implement the i2c module in a really i2c IC. I look around and I found a TMP421 resting so I decided to try reading it. http://www.ti.com/lit/ds/sbos398c/sbos398c.pdf

 

As I don't have a logic analyzer avaiable, I'm trying to use chipscope to read the values from the sensor.

 

Below, the current vhdl code:

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    17:45:53 03/09/2014 
-- Design Name: 
-- Module Name:    i2c - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity i2c is
    Port ( CLK_27MHz : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           i2c_sda : inout  STD_LOGIC;
           i2c_scl : out  STD_LOGIC);
end i2c;

architecture Behavioral of i2c is
	
	
	constant IDLE : std_logic_vector :="0000";
	constant START : std_logic_vector :="0001";
	constant ADDRESS :  std_logic_vector :="0010";
	constant RW :  std_logic_vector :="0011";
	constant ACK :  std_logic_vector :="0100";
	constant DATA &colon;  std_logic_vector :="0101";
	constant ACK2 :  std_logic_vector :="0110";
	constant DATA2 :  std_logic_vector :="0111";
	constant NACK :  std_logic_vector :="1000";
	constant STOP :  std_logic_vector :="1001";
	
	signal clk: std_logic := '0';
	signal Counter: std_logic_vector (6 downto 0);
	signal addr: std_logic_vector (6 downto 0) := (others => '0');
	signal dat: std_logic_vector (6 downto 0) := (others => '0');
	signal dat2: std_logic_vector (6 downto 0) := (others => '0');
	signal i2c_scl_signal: std_logic;
	
	signal state: std_logic_vector (3 downto 0);


begin

	Prescaler: process (CLK_27MHz)
	begin
		if rising_edge(CLK_27MHz) then
			if Counter < "1000011" then
				Counter <= Counter + 1;
			else
				clk<=not clk;
				Counter <= (others=>'0');
			end if;
		end if;
	end process Prescaler;
	
	

	I2C: Process(clk)
	
	variable Counter : integer range 0 to 7;
	
	begin
			
		if rising_edge(clk) then
			if reset = '1' then
				state <= IDLE;
				i2c_sda <= '1';
				i2c_scl <= '1';
				addr <= "1001100";
--				dat <= "0001010";
				Counter := 0;
				
			elsif state = IDLE or state = START or state = STOP then
				i2c_scl_signal <= '1';
								
			else
				i2c_scl_signal <= not i2c_scl_signal;
				i2c_scl <= not i2c_scl_signal;
			end if;
		
			case state is
			
				when IDLE =>
					i2c_sda <= '1';
					state <= START;
				
				when START =>
					i2c_sda <= '0';
					state <= ADDRESS;
					Counter := 6;
					
				when ADDRESS =>
					i2c_sda <= addr(Counter);
					if Counter = 0 then state <= RW;
					else Counter := Counter -1;
					end if;
					
				when RW =>
					i2c_sda <= '1';
					state <= ACK;
					
				when ACK =>
					if i2c_sda = '0' then
						state <= DATA;
						Counter := 6;
					end if;
					
				when DATA =>
					dat(Counter)<=i2c_sda;
					if Counter = 0 then state <= ACK2;
					else Counter := Counter - 1;
					end if;
					
				when ACK2 =>
					if i2c_sda = '0' then
						state <= DATA2;
						Counter := 6;
					end if;
					
				when DATA2 =>
					dat2(Counter)<=i2c_sda;
					if Counter = 0 then state <= NACK;
					else Counter := Counter - 1;
					end if;					
				
				when NACK =>
					i2c_sda <= '1';
					state <= STOP;
					
				when STOP =>
					i2c_sda <= '1';	
					state <= IDLE;		

				when others => state <= IDLE;
					
			
			end case;
			
		end if;
	end Process I2C;


end Behavioral;

 The problem is...I can't read anything...The SDA line doesn't send or reads any addresses.. There are the waveforms that I get:

 

cs_i2c.jpg

 

when I press the reset button, the SDA gets strange, why??

 

cs_i2c_reset.jpg

 

I don't have a logic analyzer avaiable but I used my digital osciloscope and I get similar results from the ones you can see above.

 

What I am doing wrong?

 

0 Kudos
Reply
Historian
Historian
10,423 Views
Registered: ‎02-25-2008

Two things:

 

a) Without seeing a test bench and a model of the I2C slave, we can't guess at why it doesn't work.

 

b) Stop using std_logic_vectors to count. Use a natural.

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
10,419 Views
Registered: ‎12-10-2013


@bassman59 wrote:

Two things:

 

a) Without seeing a test bench and a model of the I2C slave, we can't guess at why it doesn't work.

 

b) Stop using std_logic_vectors to count. Use a natural.


 

a) Are you asking for these???cs1.jpg

cs2.jpgcs3.jpgmodel.jpg

 

b) I'll look into it. Thank you for the tip.

0 Kudos
Reply
Historian
Historian
7,552 Views
Registered: ‎02-25-2008

No. ChipScope is no replacement for a proper simulation test bench.

 

You must simulate and verify your design before you even think about implementation in hardware.

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
7,545 Views
Registered: ‎12-10-2013


@bassman59 wrote:

No. ChipScope is no replacement for a proper simulation test bench.

 

You must simulate and verify your design before you even think about implementation in hardware.


Humm...My knowlegde on simulation test bench is still very limited. Would you please tell me about a good pdf that teaches how to write the VHDL test bench?

 

In this case I don't know how to send a 0 through the sda line when the state is ACK and how to simulate like if the sensor were sending the data using the SDA line as well....

 

Currently, my file is like this:

 

--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   23:30:02 03/09/2014
-- Design Name:   
-- Module Name:   D:/fpga_aprender/i2c/test_step1.vhd
-- Project Name:  i2c
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: i2c
-- 
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes: 
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation 
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY test_step1 IS
END test_step1;
 
ARCHITECTURE behavior OF test_step1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT i2c
    PORT(
         CLK_27MHz : IN  std_logic;
         reset : IN  std_logic;
         i2c_sda : INOUT  std_logic;
         i2c_scl : OUT  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal CLK_27MHz : std_logic := '0';
   signal reset : std_logic := '0';

 	--Outputs
   signal i2c_sda : std_logic;
   signal i2c_scl : std_logic;

   -- Clock period definitions
   constant clk_period : time := 37 ns;
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: i2c PORT MAP (
          CLK_27MHz => CLK_27MHz,
          reset => reset,
          i2c_sda => i2c_sda,
          i2c_scl => i2c_scl
        );

   -- Clock process definitions
   clk_process :process
   begin
		CLK_27MHz <= '0';
		wait for clk_period/2;
		CLK_27MHz <= '1';
		wait for clk_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin		
		reset <= '1';
      wait for clk_period;
		reset <= '0';
		
      -- insert stimulus here 

      wait;
   end process;

END;

 Thank you!

0 Kudos
Reply
Historian
Historian
7,525 Views
Registered: ‎02-25-2008


@nnunes wrote:

@bassman59 wrote:

No. ChipScope is no replacement for a proper simulation test bench.

 

You must simulate and verify your design before you even think about implementation in hardware.


Humm...My knowlegde on simulation test bench is still very limited. Would you please tell me about a good pdf that teaches how to write the VHDL test bench?

 


The only real reference that's of any use is Janick Bergeron's "Writing Testbenches" text. The latest edition is probably expensive and covers stuff that's beyond VHDL test benches, so an earlier edition is still useful. 

 

But, put simply, you must have a VHDL model of your I2C bus slave device, and your master in your FPGA interacts with that slave in the simulation.

----------------------------Yes, I do this for a living.
0 Kudos
Reply
Visitor
Visitor
7,218 Views
Registered: ‎12-10-2013


@bassman59 wrote:
 But, put simply, you must have a VHDL model of your I2C bus slave device, and your master in your FPGA interacts with that slave in the simulation.

I'm having some trouble doing that. Probably it's some roockie mistake...

 

I have the i2c.vhd :

 

entity i2c is
    Port ( CLK_27MHz : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           i2c_sda : inout  STD_LOGIC;
           i2c_scl : out  STD_LOGIC);
end i2c;

architecture Behavioral of i2c is


etc
etc

Then  I have the tmp421.vhd as slave:

 

entity tmp421 is
    Port ( tmp_sda : inout  STD_LOGIC;
           tmp_scl : in  STD_LOGIC);
end tmp421;

architecture Behavioral of tmp421 is

etc

 To interconnect these models in the testbench I am doing the following:

 

IBRARY ieee;
USE ieee.std_logic_1164.ALL;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY test_step1 IS
END test_step1;
 
ARCHITECTURE behavior OF test_step1 IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT i2c
    PORT(
         CLK_27MHz : IN  std_logic;
         reset : IN  std_logic;
         i2c_sda : INOUT  std_logic;
         i2c_scl : OUT  std_logic
        );
    END COMPONENT;
    
	 COMPONENT TMP421
    PORT(
         tmp_sda : INOUT  std_logic;
         tmp_scl : OUT  std_logic
        );
    END COMPONENT;
    
	 For all: i2c use entity work.i2c;
	 For all: TMP421 use entity work.tmp421;

   --Inputs
   signal CLK_27MHz : std_logic := '0';
   signal reset : std_logic := '0';

 	--Outputs
   signal i2c_sda : std_logic;
   signal i2c_scl : std_logic;
	
	signal tmp_sda : std_logic;
   signal tmp_scl : std_logic;

   -- Clock period definitions
   constant clk_period : time := 37 ns;
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: i2c PORT MAP (
          CLK_27MHz => CLK_27MHz,
          reset => reset,
          i2c_sda => tmp_sda,
          i2c_scl => tmp_scl
        );
		  
	
   -- Clock process definitions
   clk_process :process
   begin
		CLK_27MHz <= '0';
		wait for clk_period/2;
		CLK_27MHz <= '1';
		wait for clk_period/2;
   end process;
 

   -- Stimulus process
	stim_proc: process
	   begin		
		reset <= '1';
      wait for clk_period;
		reset <= '0';		
		
      -- insert stimulus here 
		
      wait;
   end process;

END;

 I don't get any errors but I can't simulate this because it doesn't generate the clock...Maybe it is something wrong in the Instatiation. Would you please give an hint on this?

 

 

Thank you!

0 Kudos
Reply
Historian
Historian
7,215 Views
Registered: ‎02-25-2008

Some comments:

 

a) Stop using the old-style component declaration and instantiation, and instead use direct entity instantiation. In other words, delete the component declarations, and for the lower-level entity instantiations you write something like:

 

    u_foo : entity work.foo 

        port map (

            ... signals ...

        );

 

Less typing, less duplication, and less prone to making mistakes.

 

b) " I can't simulate this because it doesn't generate the clock...Maybe it is something wrong in the Instatiation. Would you please give an hint on this?"

 

Your CLK_27MHZ generator looks correct.

 

----------------------------Yes, I do this for a living.
0 Kudos
Reply