Autor Tema: I2C maestro VHDL  (Leído 12160 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
I2C maestro VHDL
« en: 16 de Mayo de 2012, 14:48:41 »
Hola  ;-)

Quiero leer los datos de un ADXL345...

http://www.analog.com/en/mems-sensors/mems-inertial-sensors/adxl345/products/product.html

... el cual está conectado a mi FPGA. El problema es que la IP de Altera no tiene módulos I2C en el SOPC Builder ni en el MegaWizard.  :8}

Estuve buscando mucho en internet y pues siempre caía en OpenCores.org, en donde hay un módulo en Verilog y en VHDL.

http://opencores.org/project,i2c

Dice que es compatible con el bus Avalon de Altera, lo quise agregar pero es un mundo de conexiones y pues ni cómo. Luego revisé los fuentes y di con el archivo viejo I2C.vhd y parece ser que me serviría, pero lo quise simular en ModelSim y no logré que generara señal alguna.

¿Alguien tiene un módulo I2C funcionando o sabe de dónde bajarlo? ¿O me podrían ayudar a echar a andar el módulo de OpenCores?

Gracias.

Edito: Parece ser que puedo leer el ADX por SPI de 3 líneas en vez de I2C... :S
« Última modificación: 16 de Mayo de 2012, 14:56:52 por migsantiago »

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: I2C maestro VHDL
« Respuesta #1 en: 16 de Mayo de 2012, 15:27:05 »
Puede que esto sirva  :mrgreen:

http://pastebin.com/DrarAQr7#

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #2 en: 16 de Mayo de 2012, 17:02:43 »
No se porque, pero no puedo ingresar a OpenCores, me registré y ahora no me toma la contraseña, la cambié y tampoco  :x
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: I2C maestro VHDL
« Respuesta #3 en: 17 de Mayo de 2012, 12:46:44 »

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #4 en: 17 de Mayo de 2012, 12:48:33 »
Ayer finalmente pude, y estuve estudiando como crear un modulo para NiosII. Quede medio colgado con el tipo de señales que hay que colocar...  :x Despues vi el tema de realizarlo en VHDL y no parece complicado, aplicando una maquina de estados, pero es largooo!
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: I2C maestro VHDL
« Respuesta #5 en: 17 de Mayo de 2012, 13:01:05 »
Sí, una FSM es lo ideal. Lo del bus Avalon está rudo.

Voy a ver qué logro... modificaré el I2C que encontré arriba. Quise usar SPI de 3 hilos pero el SOPC no lo tiene buuuu

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #6 en: 17 de Mayo de 2012, 19:51:22 »
http://opencores.org/project,i2c

Dice que es compatible con el bus Avalon de Altera, lo quise agregar pero es un mundo de conexiones y pues ni cómo.

De todo lo que lei y experimenté, no se como puede ser que sea compatible con el bus Avalon  :? Comento esto porque de implementarlo para bus Avalon, en lugar de usar varias señales para iniciar el Start, Stop, Read, Write, etc.. usaría un solo bus y un direccionador para acceder a cada registro y/o a cada bit. Para solucionarlo habría que crear otro VHDL que sea de intermediario cumpliendo lo requerido por Bus Avalon y que instancie a i2c_simple o i2c_core. Igual no es palabra santa, tengo poca experiencia  :mrgreen:


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #7 en: 18 de Mayo de 2012, 17:06:51 »
Hola! En base a lo que comenté anteriormente hice un vhdl de intermediario: i2c_avalon para trabajar con i2c_simple :mrgreen:

Código: VHDL
  1. library IEEE;
  2. use ieee.std_logic_1164.all;
  3. use ieee.std_logic_arith.all;
  4. use ieee.std_logic_unsigned.all;
  5.  
  6. use work.i2c.all;
  7.  
  8. -- Escritura
  9. -- Address 0 -> Clk_Cnt (Para Frecuencia de I2C)
  10. -- Address 1 -> Data a enviar
  11. -- Address 2 -> Registro con bit para Start,Stop,Read,Write...
  12. -- Lectura
  13. -- Address 0 -> Status
  14. -- Address 1 -> Data
  15.  
  16. entity i2c_avalon is
  17.         port (
  18.                 -- Entradas
  19.                 clk: in std_logic;             
  20.                 reset_n: in std_logic;
  21.                 chipselect: in std_logic;
  22.                 write: in std_logic;
  23.                 read: in std_logic;
  24.                 address: in std_logic_vector (1 downto 0);                              --
  25.                 writedata: in std_logic_vector (7 downto 0); --
  26.                 -- Salida
  27.                 readdata: out std_logic_vector(7 downto 0);
  28.                 -- i2c signals
  29.                 pSCL : inout std_logic;
  30.                 pSDA : inout std_logic
  31.         );
  32. end i2c_avalon;
  33.  
  34. architecture behavior of i2c_avalon is
  35.         signal sg_start,sg_stop,sg_read,sg_write,sg_ackin,sg_ackout,sg_cmdack: std_logic;
  36.         signal sg_cmds: std_logic_vector(7 downto 0); -- start,stop,read,write,ack_in
  37.         signal sg_status: std_logic_vector(7 downto 0); -- ack_out, cmd_ack
  38.         signal sg_clkcnt: unsigned(7 downto 0);
  39.         signal sg_Din: std_logic_vector(7 downto 0);
  40.         signal sg_Dout: std_logic_vector(7 downto 0);
  41.         signal sg_SelectRead: std_logic_vector(7 downto 0);
  42.         signal sg_wr,sg_wr_clkcnt,sg_wr_Din,sg_wr_cmds,sg_rd: std_logic;
  43.         signal sg_ena: std_logic:='0';
  44. begin  
  45.         U0: simple_i2c port map(
  46.                 clk=>clk,
  47.                 ena=>sg_ena,
  48.                 nReset=>reset_n,
  49.                 clk_cnt=>sg_clkcnt,
  50.                 start=>sg_start,
  51.                 stop=>sg_stop,
  52.                 read=>sg_read,
  53.                 write=>sg_write,
  54.                 ack_in=>sg_ackin,
  55.                 Din=>sg_Din,
  56.                 cmd_ack=>sg_cmdack,
  57.                 ack_out=>sg_ackout,
  58.                 Dout=>sg_Dout,
  59.                 SCL=>pSCL,
  60.                 SDA=>pSDA
  61.         );
  62.        
  63.         process(clk,reset_n)
  64.         begin
  65.                 if(reset_n='0')then
  66.                         sg_cmds<=(others =>'0');
  67.                         sg_Din<=(others =>'0');
  68.                         sg_clkcnt<="00000001";
  69.                         readdata<=(others =>'0');
  70.                 elsif rising_edge(clk) then
  71.                         if(sg_wr_clkcnt='1')then
  72.                                 sg_clkcnt<=unsigned(writedata);
  73.                         end if;
  74.                         if(sg_wr_Din='1')then
  75.                                 sg_Din<=writedata;
  76.                         end if;
  77.                         if(sg_wr_cmds='1')then
  78.                                 sg_cmds<=writedata;
  79.                         end if;
  80.                         if(sg_rd='1')then
  81.                                 readdata<=sg_SelectRead;
  82.                         end if;
  83.                 end if;
  84.         end process;
  85.        
  86.         sg_wr<='1' when chipselect='1' and write='1' else '0';
  87.         sg_wr_clkcnt<='1' when address="00" and sg_wr='1' else '0';
  88.         sg_wr_Din<='1' when address="01" and sg_wr='1' else '0';
  89.         sg_wr_cmds<='1' when address="10" and sg_wr='1' else '0';
  90.         sg_rd<='1' when chipselect='1' and read='1' else '0';
  91.        
  92.         sg_start<=sg_cmds(0);
  93.         sg_stop<=sg_cmds(1);
  94.         sg_read<=sg_cmds(2);
  95.         sg_write<=sg_cmds(3);
  96.         sg_ackin<=sg_cmds(4);
  97.         sg_ena<=sg_cmds(5);
  98.        
  99.         sg_status(0)<=sg_ackout;
  100.         sg_status(1)<=sg_cmdack;       
  101.        
  102.         sg_SelectRead<=sg_status when address="00" and sg_rd='1' else
  103.                                    sg_Dout when address="01" and sg_rd='1' else "00000000";
  104. end architecture;


En base a eso cree el componente para Nios II:



Con nombre sk_i2c. Eso crea las definiciones SK_I2C_.....

Ahora según como se implementa el direccionamiento, para trabajar con el módulo las funciones serían:

Código: C
  1. #include "system.h"
  2. #include "alt_types.h"
  3.  
  4. #define __I2C_CALC_ADDRESS_DYNAMIC(BASE, OFFSET)        ((void *)(((alt_u8*)BASE) + (OFFSET)))
  5. #define I2C_RD(BASE, OFFSET)                                            __builtin_ldbuio (__I2C_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
  6. #define I2C_WR(BASE, OFFSET, DATA)                              __builtin_stbio (__I2C_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
  7.  
  8. #include "sk_i2c.h"
  9. // *-------------------------------------------------------------------------*
  10. void i2c_SetClock(alt_u8 Div){
  11.  
  12.         I2C_WR(SK_I2C_BASE,2,0x00); // 000000 |ena,ack_in,write,read,stop,start
  13.         I2C_WR(SK_I2C_BASE,0,Div);
  14.         I2C_WR(SK_I2C_BASE,2,0x20); // 100000 |ena,ack_in,write,read,stop,start
  15. }
  16. // *-------------------------------------------------------------------------*
  17. void i2c_Start(void){
  18.         alt_u32 temp;
  19.  
  20.         I2C_WR(SK_I2C_BASE,2,0x21); // 100001 |ena,ack_in,write,read,stop,start
  21.         do{
  22.                 temp=I2C_RD(SK_I2C_BASE, 0);
  23.         }while((temp&0x02)==0x02);   // if cmd_ack==1?
  24. }
  25. // *-------------------------------------------------------------------------*
  26. void i2c_Stop(void){
  27.         alt_u32 temp;
  28.  
  29.         I2C_WR(SK_I2C_BASE,2,0x22); // 100010 |ena,ack_in,write,read,stop,start
  30.         do{
  31.                 temp=I2C_RD(SK_I2C_BASE, 0);
  32.         }while((temp&0x02)==0x02);   // if cmd_ack==1?
  33. }
  34. // *-------------------------------------------------------------------------*
  35. alt_u8 i2c_WriteData(alt_u8 Data){
  36.         alt_u32 temp;
  37.  
  38.         I2C_WR(SK_I2C_BASE,2,0x28); // 101000 |ena,ack_in,write,read,stop,start
  39.         I2C_WR(SK_I2C_BASE,1,Data); //
  40.         do{
  41.                 temp=I2C_RD(SK_I2C_BASE, 0);
  42.         }while((temp&0x02)==0x02);   // if cmd_ack==1?
  43.  
  44.         if((temp&0x01)==0x01){
  45.                 return(1);
  46.         }
  47.         return(0);
  48. }
  49. // *-------------------------------------------------------------------------*
  50. alt_u8 i2c_ReadData(alt_u8 ack){
  51.         alt_u32 temp;
  52.  
  53.         I2C_WR(SK_I2C_BASE,2,0x24|((ack&0x01)<<4)); // 1x0010 |ena,ack_in,write,read,stop,start
  54.         do{
  55.                 temp=I2C_RD(SK_I2C_BASE, 0);
  56.         }while((temp&0x02)==0x02);   // if cmd_ack==1?
  57.  
  58.         return((alt_u8)I2C_RD(SK_I2C_BASE, 1));
  59. }

Todavía no lo pruebo, tengo que armar algo con I2C para probarlo, pero para dar una idea.  :)

A ver si me sale armar el i2c_master_top  :?
« Última modificación: 19 de Mayo de 2012, 15:45:52 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: I2C maestro VHDL
« Respuesta #8 en: 19 de Mayo de 2012, 00:00:56 »
Ok!

Si quieres simúlalo primero en ModelSim. Yo espero tus resultados porque no sé qué tanto hayas hecho  :D

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #9 en: 19 de Mayo de 2012, 17:07:44 »
Si quieres simúlalo primero en ModelSim.

Que paso ahi, proteus no pero ModelSim si!  :D Pareciera que funciona  :mrgreen: el analizador lógico no lo tengo a disposición como para revisarlo detalladamente..

Este sería para la versión completa del i2c master:

Código: VHDL
  1. ---------------------------------------------------------------------
  2. ----                                                             ----
  3. ----  WISHBONE revB2 compl. I2C Master Core; top level           ----
  4. ----                                                             ----
  5. ----                                                             ----
  6. ----  Author: Richard Herveille                                  ----
  7. ----          richard@asics.ws                                   ----
  8. ----          www.asics.ws                                       ----
  9. ----                                                             ----
  10. ----  Downloaded from: http://www.opencores.org/projects/i2c/    ----
  11. ----                                                             ----
  12. ---------------------------------------------------------------------
  13. ----                                                             ----
  14. ---- Copyright (C) 2000 Richard Herveille                        ----
  15. ----                    richard@asics.ws                         ----
  16. ----                                                             ----
  17. ---- This source file may be used and distributed without        ----
  18. ---- restriction provided that this copyright statement is not   ----
  19. ---- removed from the file and that any derivative work contains ----
  20. ---- the original copyright notice and the associated disclaimer.----
  21. ----                                                             ----
  22. ----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
  23. ---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
  24. ---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
  25. ---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
  26. ---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ----
  27. ---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ----
  28. ---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ----
  29. ---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ----
  30. ---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ----
  31. ---- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ----
  32. ---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ----
  33. ---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ----
  34. ---- POSSIBILITY OF SUCH DAMAGE.                                 ----
  35. ----                                                             ----
  36. ---------------------------------------------------------------------
  37.  
  38. --  CVS Log
  39. --
  40. --  $Id: i2c_master_top.vhd,v 1.8 2009-01-20 10:38:45 rherveille Exp $
  41. --
  42. --  $Date: 2009-01-20 10:38:45 $
  43. --  $Revision: 1.8 $
  44. --  $Author: rherveille $
  45. --  $Locker:  $
  46. --  $State: Exp $
  47. --
  48. -- Change History:
  49. --               Revision 1.8 2012/05/16  Suky (www.micros-designs.com.ar)
  50. --               Se adecua port para implementacion en BUS AVALON (Altera NIOS II)
  51. --
  52. --               Revision 1.7  2004/03/14 10:17:03  rherveille
  53. --               Fixed simulation issue when writing to CR register
  54. --
  55. --               Revision 1.6  2003/08/09 07:01:13  rherveille
  56. --               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
  57. --               Fixed a potential bug in the byte controller's host-acknowledge generation.
  58. --
  59. --               Revision 1.5  2003/02/01 02:03:06  rherveille
  60. --               Fixed a few 'arbitration lost' bugs. VHDL version only.
  61. --
  62. --               Revision 1.4  2002/12/26 16:05:47  rherveille
  63. --               Core is now a Multimaster I2C controller.
  64. --
  65. --               Revision 1.3  2002/11/30 22:24:37  rherveille
  66. --               Cleaned up code
  67. --
  68. --               Revision 1.2  2001/11/10 10:52:44  rherveille
  69. --               Changed PRER reset value from 0x0000 to 0xffff, conform specs.
  70. --       
  71.  
  72. library ieee;
  73. use ieee.std_logic_1164.all;
  74. use ieee.std_logic_unsigned.all;
  75. use ieee.numeric_std.all;
  76.  
  77.  
  78. entity i2c_master_top is
  79.     generic(
  80.             ARST_LVL : std_logic := '0'                   -- asynchronous reset level
  81.     );
  82.     port   (
  83.             -- wishbone signals
  84.             clk           : in  std_logic;                    -- master clock input
  85.             nreset        : in  std_logic := '1';             -- asynchronous reset
  86.             address       : in  std_logic_vector(2 downto 0); -- lower address bits
  87.             writedata     : in  std_logic_vector(7 downto 0); -- Databus input
  88.             readdata      : out std_logic_vector(7 downto 0); -- Databus output
  89.             write         : in  std_logic;                    -- Write enable input
  90.             read                  : in  std_logic;                                        -- Read enable
  91.             chipselect    : in  std_logic;                    -- Strobe signals / core select signal
  92.             interrupt     : out std_logic;                    -- interrupt request output signal
  93.  
  94.             -- i2c lines
  95.             scl_pad_i     : in  std_logic;                    -- i2c clock line input
  96.             scl_pad_o     : out std_logic;                    -- i2c clock line output
  97.             scl_padoen_o  : out std_logic;                    -- i2c clock line output enable, active low
  98.             sda_pad_i     : in  std_logic;                    -- i2c data line input
  99.             sda_pad_o     : out std_logic;                    -- i2c data line output
  100.             sda_padoen_o  : out std_logic                     -- i2c data line output enable, active low
  101.     );
  102. end entity i2c_master_top;
  103.  
  104. architecture structural of i2c_master_top is
  105.     component i2c_master_byte_ctrl is
  106.     port (
  107.           clk    : in std_logic;
  108.           rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
  109.           nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
  110.           ena    : in std_logic; -- core enable signal
  111.  
  112.           clk_cnt : in unsigned(15 downto 0); -- 4x SCL
  113.  
  114.           -- input signals
  115.           start,
  116.           stop,
  117.           read,
  118.           write,
  119.           ack_in : in std_logic;
  120.           din    : in std_logic_vector(7 downto 0);
  121.  
  122.           -- output signals
  123.           cmd_ack  : out std_logic;
  124.           ack_out  : out std_logic;
  125.           i2c_busy : out std_logic;
  126.           i2c_al   : out std_logic;
  127.           dout     : out std_logic_vector(7 downto 0);
  128.  
  129.           -- i2c lines
  130.           scl_i   : in std_logic;  -- i2c clock line input
  131.           scl_o   : out std_logic; -- i2c clock line output
  132.           scl_oen : out std_logic; -- i2c clock line output enable, active low
  133.           sda_i   : in std_logic;  -- i2c data line input
  134.           sda_o   : out std_logic; -- i2c data line output
  135.           sda_oen : out std_logic  -- i2c data line output enable, active low
  136.     );
  137.     end component i2c_master_byte_ctrl;
  138.  
  139.     -- registers
  140.     signal prer : unsigned(15 downto 0);             -- clock prescale register
  141.     signal ctr  : std_logic_vector(7 downto 0);      -- control register
  142.     signal txr  : std_logic_vector(7 downto 0);      -- transmit register
  143.     signal rxr  : std_logic_vector(7 downto 0);      -- receive register
  144.     signal cr   : std_logic_vector(7 downto 0);      -- command register
  145.     signal sr   : std_logic_vector(7 downto 0);      -- status register
  146.  
  147.     -- internal reset signal
  148.     signal rst_i : std_logic;
  149.  
  150.     -- wishbone write access
  151.     signal wb_wacc : std_logic;
  152.    
  153.     signal wb_racc : std_logic;
  154.  
  155.     -- internal acknowledge signal
  156.     signal iack_o : std_logic;
  157.  
  158.     -- done signal: command completed, clear command register
  159.     signal done : std_logic;
  160.  
  161.     -- command register signals
  162.     signal sta, sto, rd, wr, ack, iack : std_logic;
  163.  
  164.     signal core_en : std_logic;                      -- core enable signal
  165.     signal ien     : std_logic;                      -- interrupt enable signal
  166.  
  167.     -- status register signals
  168.     signal irxack, rxack : std_logic;                -- received aknowledge from slave
  169.     signal tip           : std_logic;                -- transfer in progress
  170.     signal irq_flag      : std_logic;                -- interrupt pending flag
  171.     signal i2c_busy      : std_logic;                -- i2c bus busy (start signal detected)
  172.     signal i2c_al, al    : std_logic;                -- arbitration lost
  173.  
  174. begin
  175.     -- generate internal reset signal
  176.     rst_i <= nreset xor ARST_LVL;
  177.  
  178.     wb_wacc <= write and chipselect; -- write and selectchip
  179.     wb_racc <= read and chipselect;
  180.  
  181.     -- assign readdata
  182.     assign_dato : process(clk)
  183.     begin
  184.         if (clk'event and clk = '1') then
  185.                         if(wb_racc='1')then
  186.                                 case address is
  187.                                         when "000"  => readdata <= std_logic_vector(prer( 7 downto 0));
  188.                                         when "001"  => readdata <= std_logic_vector(prer(15 downto 8));
  189.                                         when "010"  => readdata <= ctr;
  190.                                         when "011"  => readdata <= rxr; -- write is transmit register TxR
  191.                                         when "100"  => readdata <= sr;  -- write is command register CR
  192.  
  193.                                         -- Debugging registers:
  194.                                         -- These registers are not documented.
  195.                                         -- Functionality could change in future releases
  196.                                         when "101"  => readdata <= txr;
  197.                                         when "110"  => readdata <= cr;
  198.                                         when "111"  => readdata <= (others => '0');
  199.                                         when others => readdata <= (others => 'X'); -- for simulation only
  200.                                 end case;
  201.             end if;
  202.         end if;
  203.     end process assign_dato;
  204.  
  205.  
  206.     -- generate registers (CR, SR see below)
  207.     gen_regs: process(rst_i, clk)
  208.     begin
  209.         if (rst_i = '0') then
  210.             prer <= (others => '1');
  211.             ctr  <= (others => '0');
  212.             txr  <= (others => '0');
  213.         elsif (clk'event and clk = '1') then
  214.                if (wb_wacc = '1') then
  215.                    case address is
  216.                        when "000" => prer( 7 downto 0) <= unsigned(writedata);
  217.                        when "001" => prer(15 downto 8) <= unsigned(writedata);
  218.                        when "010" => ctr               <= writedata;
  219.                        when "011" => txr               <= writedata;
  220.                        when "100" => null; --write to CR, avoid executing the others clause
  221.  
  222.                       -- illegal cases, for simulation only
  223.                       when others =>
  224.                           report ("Illegal write address, setting all registers to unknown.");
  225.                           prer <= (others => 'X');
  226.                           ctr  <= (others => 'X');
  227.                           txr  <= (others => 'X');
  228.                    end case;
  229.                end if;
  230.         end if;
  231.     end process gen_regs;
  232.  
  233.  
  234.     -- generate command register
  235.     gen_cr: process(rst_i, clk)
  236.     begin
  237.         if (rst_i = '0') then
  238.             cr <= (others => '0');
  239.         elsif (clk'event and clk = '1') then
  240.             if (wb_wacc = '1') then
  241.                 if ( (core_en = '1') and (address = "100") ) then
  242.                     -- only take new commands when i2c core enabled
  243.                     -- pending commands are finished
  244.                     cr <= writedata;
  245.                 end if;
  246.             else
  247.                 if (done = '1' or i2c_al = '1') then
  248.                     cr(7 downto 4) <= (others => '0'); -- clear command bits when command done or arbitration lost
  249.                 end if;
  250.  
  251.                 cr(2 downto 1) <= (others => '0');   -- reserved bits, always '0'
  252.                 cr(0) <= '0';                        -- clear IRQ_ACK bit
  253.             end if;
  254.         end if;
  255.     end process gen_cr;
  256.  
  257.     -- decode command register
  258.     sta  <= cr(7);
  259.     sto  <= cr(6);
  260.     rd   <= cr(5);
  261.     wr   <= cr(4);
  262.     ack  <= cr(3);
  263.     iack <= cr(0);
  264.  
  265.     -- decode control register
  266.     core_en <= ctr(7);
  267.     ien     <= ctr(6);
  268.  
  269.     -- hookup byte controller block
  270.     byte_ctrl: i2c_master_byte_ctrl
  271.     port map (
  272.               clk      => clk,
  273.               rst      => '0',
  274.               nReset   => rst_i,
  275.               ena      => core_en,
  276.               clk_cnt  => prer,
  277.               start    => sta,
  278.               stop     => sto,
  279.               read     => rd,
  280.               write    => wr,
  281.               ack_in   => ack,
  282.               i2c_busy => i2c_busy,
  283.               i2c_al   => i2c_al,
  284.               din      => txr,
  285.               cmd_ack  => done,
  286.               ack_out  => irxack,
  287.               dout     => rxr,
  288.               scl_i    => scl_pad_i,
  289.               scl_o    => scl_pad_o,
  290.               scl_oen  => scl_padoen_o,
  291.               sda_i    => sda_pad_i,
  292.               sda_o    => sda_pad_o,
  293.               sda_oen  => sda_padoen_o
  294.     );
  295.  
  296.  
  297.     -- status register block + interrupt request signal
  298.     st_irq_block : block
  299.     begin
  300.         -- generate status register bits
  301.         gen_sr_bits: process (clk, rst_i)
  302.         begin
  303.             if (rst_i = '0') then
  304.                 al       <= '0';
  305.                 rxack    <= '0';
  306.                 tip      <= '0';
  307.                 irq_flag <= '0';
  308.             elsif (clk'event and clk = '1') then
  309.                                 al       <= i2c_al or (al and not sta);
  310.                                 rxack    <= irxack;
  311.                                 tip      <= (rd or wr);
  312.  
  313.                                 -- interrupt request flag is always generated
  314.                                 irq_flag <= (done or i2c_al or irq_flag) and not iack;
  315.             end if;
  316.         end process gen_sr_bits;
  317.  
  318.         -- generate interrupt request signals
  319.         gen_irq: process (clk, rst_i)
  320.         begin
  321.             if (rst_i = '0') then
  322.                 interrupt <= '0';
  323.             elsif (clk'event and clk = '1') then
  324.                                 -- interrupt signal is only generated when IEN (interrupt enable bit) is set
  325.                 interrupt <= irq_flag and ien;
  326.             end if;
  327.         end process gen_irq;
  328.  
  329.         -- assign status register bits
  330.         sr(7)          <= rxack;
  331.         sr(6)          <= i2c_busy;
  332.         sr(5)          <= al;
  333.         sr(4 downto 2) <= (others => '0'); -- reserved
  334.         sr(1)          <= tip;
  335.         sr(0)          <= irq_flag;
  336.     end block;
  337.  
  338. end architecture structural;

Las funciones son medias parecidas:

Código: C
  1. #include "system.h"
  2. #include "alt_types.h"
  3.  
  4. /*
  5.  * Definitions for the Opencores i2c master core
  6.  */
  7. #define __I2C_CALC_ADDRESS_DYNAMIC(BASE, OFFSET)        ((void *)(((alt_u8*)BASE) + (OFFSET)))
  8. #define I2C_RD(BASE, OFFSET)                                            __builtin_ldbuio (__I2C_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
  9. #define I2C_WR(BASE, OFFSET, DATA)                              __builtin_stbio (__I2C_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
  10. /* --- Definitions for i2c master's registers --- */
  11.  
  12. /* ----- Read-write access                                            */
  13.  
  14. #define OC_I2C_PRER_LO 0x00     /* Low byte clock prescaler register  */
  15. #define OC_I2C_PRER_HI 0x01     /* High byte clock prescaler register */
  16. #define OC_I2C_CTR     0x02     /* Control register                   */
  17.  
  18. /* ----- Write-only registers                                         */
  19.  
  20. #define OC_I2C_TXR     0x03     /* Transmit byte register             */
  21. #define OC_I2C_CR      0x04     /* Command register                   */
  22.  
  23. /* ----- Read-only registers                                          */
  24.  
  25. #define OC_I2C_RXR     0x03     /* Receive byte register              */
  26. #define OC_I2C_SR      0x04     /* Status register                    */
  27.  
  28. /* ----- Bits definition                                              */
  29.  
  30. /* ----- Control register                                             */
  31.  
  32. #define OC_I2C_EN (1<<7)        /* Core enable bit:                   */
  33.                                 /*      1 - core is enabled           */
  34.                                 /*      0 - core is disabled          */
  35. #define OC_I2C_IEN (1<<6)       /* Interrupt enable bit               */
  36.                                 /*      1 - Interrupt enabled         */
  37.                                 /*      0 - Interrupt disabled        */
  38.                                 /* Other bits in CR are reserved      */
  39.  
  40. /* ----- Command register bits                                        */
  41.  
  42. #define OC_I2C_STA (1<<7)       /* Generate (repeated) start condition*/
  43. #define OC_I2C_STO (1<<6)       /* Generate stop condition            */
  44. #define OC_I2C_RD  (1<<5)       /* Read from slave                    */
  45. #define OC_I2C_WR  (1<<4)       /* Write to slave                     */
  46. #define OC_I2C_ACK (1<<3)       /* Acknowledge from slave             */
  47.                                 /*      1 - ACK                       */
  48.                                 /*      0 - NACK                      */
  49. #define OC_I2C_IACK (1<<0)      /* Interrupt acknowledge              */
  50.  
  51. /* ----- Status register bits                                         */
  52.  
  53. #define OC_I2C_RXACK (1<<7)     /* ACK received from slave            */
  54.                                 /*      1 - ACK                       */
  55.                                 /*      0 - NACK                      */
  56. #define OC_I2C_BUSY  (1<<6)     /* Busy bit                           */
  57. #define OC_I2C_TIP   (1<<1)     /* Transfer in progress               */
  58. #define OC_I2C_IF    (1<<0)     /* Interrupt flag                     */
  59.  
  60. void i2c_Init(alt_u8 Prer_lo,alt_u8 Prer_hi);
  61.  
  62. alt_u8 i2c_StartWrite(alt_u8 Data);
  63.  
  64. alt_u8 i2c_WriteStop(alt_u8 Data);

Código: C
  1. #include "i2c_master.h"
  2.  
  3. void i2c_Init(alt_u8 Prer_lo,alt_u8 Prer_hi){
  4.  
  5.         I2C_WR(I2C_MASTER_BASE, OC_I2C_CTR, 0x00);                      // disable
  6.         I2C_WR(I2C_MASTER_BASE, OC_I2C_PRER_LO, Prer_lo);
  7.         I2C_WR(I2C_MASTER_BASE, OC_I2C_PRER_HI, Prer_hi);
  8.  
  9.         I2C_WR(I2C_MASTER_BASE, OC_I2C_CTR, OC_I2C_EN);
  10. }
  11.  
  12. alt_u8 i2c_StartWrite(alt_u8 Data){
  13.         alt_u8 temp;
  14.  
  15.         I2C_WR(I2C_MASTER_BASE, OC_I2C_TXR, Data);
  16.         I2C_WR(I2C_MASTER_BASE, OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
  17.         do{
  18.                 temp=I2C_RD(I2C_MASTER_BASE, OC_I2C_SR);
  19.         }while((temp&OC_I2C_TIP)==0x00);
  20.  
  21.         if((temp&OC_I2C_RXACK)==0x00){
  22.                 return(0);
  23.         }
  24.         return(1);
  25. }
  26.  
  27. alt_u8 i2c_WriteStop(alt_u8 Data){
  28.         alt_u8 temp;
  29.  
  30.         I2C_WR(I2C_MASTER_BASE, OC_I2C_TXR, Data);
  31.         I2C_WR(I2C_MASTER_BASE, OC_I2C_CR, OC_I2C_STO|OC_I2C_WR);
  32.         do{
  33.                 temp=I2C_RD(I2C_MASTER_BASE, OC_I2C_SR);
  34.         }while((temp&OC_I2C_TIP)==0x00);
  35.  
  36.         if((temp&OC_I2C_RXACK)==0x00){
  37.                 return(0);
  38.         }
  39.         return(1);
  40. }


Adjunto los dos módulos, ahora te toca simularlos, corregir los errores, simularlo de nuevo, y....  :D :D
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: I2C maestro VHDL
« Respuesta #10 en: 19 de Mayo de 2012, 19:05:08 »
A diferencia de Proteus, ModelSim es confiable. Yo lo uso cuando termino un modelo VHDL y lo pruebo. Saco bugs rápido que no podrían verse en físico gracias a las grafiquitas de tiempo. Es buena costumbre a diferencia de Proteus jeje... cuestión de gustos.

Empezando la semana retomo lo del I2C que amablemente estás liberando. Ya te cuento qué logro.

Gracias  :mrgreen:

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #11 en: 19 de Mayo de 2012, 19:51:31 »
A diferencia de Proteus, ModelSim es confiable. Yo lo uso cuando termino un modelo VHDL y lo pruebo. Saco bugs rápido que no podrían verse en físico gracias a las grafiquitas de tiempo. Es buena costumbre a diferencia de Proteus jeje... cuestión de gustos.

Entonces habrá que probarlo  :mrgreen:
No contesto mensajes privados, las consultas en el foro

Desconectado mao707

  • PIC10
  • *
  • Mensajes: 5
Re: I2C maestro VHDL
« Respuesta #12 en: 07 de Octubre de 2013, 20:31:29 »
hola a todos!

que pena incluirme en la conversación con preguntas en vez de soluciones  :?, estoy trabajando con un sensor MPU 6050 (giroscopio y acelerómetro de 3 ejes), exactamente con este (http://www.tinkersoup.de/en/sensors/inertial-measurement-unit-imu/triple-axis-accelerometer-gyro-breakout-mpu-6050/a-760/), al igual que el tema de discusión el trabaja el protocolo I2C, debo comunicarlo con una FPGA, la referencia exacta de la fpga que poseo es una Nexys 2 (tiene una spartan 3e).

la verdad soy un novato en este tipo de comunicación  :( y pido el favor a la comunidad toda la información posible que me puedan facilitar, no se como comunicarlos, ni el código que debo generar en xilinx para recibir y manipular los datos que el sensor lee. cualquier información me será muy útil (graficos, texto, etc) estoy tratando de realizar un sistema de equilibrio sobre dos ruedas bajo el principio de péndulo invertido. les agradezco la posible ayuda que me puedan brindar.
gracias

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: I2C maestro VHDL
« Respuesta #13 en: 07 de Octubre de 2013, 21:09:13 »
Pufff... Vas a tener que estudiar bastante, aquí lo más simple es entender el protocolo, lo tedioso es implementarlo en el FPGA  :? Sobre I2C utiliza San Google, hay mucho para informarse de que se trata el protocolo.



Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado mao707

  • PIC10
  • *
  • Mensajes: 5
Re: I2C maestro VHDL
« Respuesta #14 en: 07 de Octubre de 2013, 21:21:54 »
gracias por el aporte

el protocolo lo comprendo, es un bus de dos líneas, una de ellas donde va la información (para el sensor SDA), y otra donde va la señal del reloj (scl), en lo que tengo dificultad es en el código para interpretar los datos del sensor desde xilinx ise, pz el maneja los datos del acelerómetro y giroscopio en un solo pin.

en la web he encontrado mucha información acerca de códigos para recibir y manipular estos datos, desafortunadamente todo lo hacen con pic y arduino, no consigo información con fpga  :(


 

anything