You have no items in your shopping cart.

Subtotal: 0.00

RTC interfacing with Spartan3 XC3S200 FPGA Development Kit

RTC

A real-time clock (RTC) is a computer clock (most often in the form of an integrated circuit) that keeps track of the current time. Although the term often refers to the devices in personal computers, servers and embedded systems, RTCs are present in almost any electronic device which needs to keep accurate time.

Interfacing RTC with Spartan3 FPGA Development Kit

The Spartan-3 Primer board has I2C RTC, indicated as in Figure. The SCL is clock input and is used to synchronize RTC with FPGA for various operations. When data is to be read or write, first a start condition is created followed by device address, byte address and the data itself. Finally a stop condition is provided.

I2C Protocol

mimic-diagram-for-triac

Start Condition

The start condition occurs when SDA and SCL get high to low simultaneously.

Stop Condition

The stop condition is when SDA remains low while SCL goes from high to low. The data is read or written between the start and stop conditions on every transition of SCL from high to low.

Data Transmission:

After start bit, data need to be sent at Low state of the clock and it should be stable for High state of the serial clock.

Acknowledge Condition:

After receiving address byte from FPGA, slave device must generate acknowledgement bit for single clock cycle.

DS1307:

It features the DS1307 serial real-time clock (RTC). It is a low-power, full binary-coded decimal (BCD) clock/calendar with programmable square-wave output signal. Board uses I2C interface for communication, and can only use 5V power supply. Board features a 3V/230mA lithium battery as a backup power supply which ensures that timekeeping operation continues even when the main power supply goes OFF. DS1307 operates at Regular mode 100KHz.

Schematics to interface DS1307 RTC with Spartan3 FPGA Development Kit

Schematics to interface DS1307 RTC with Spartan3 FPGA Development Kit

VHDL Code Description:

The VHDL Code for Real Time Clock is divided in to 2 parts. Write data in to RTC and Read data from RTC and send serially to UART Communication to View RTC output.

VHDL Code to write Data in RTC

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity write is
port ( 	clk : in std_logic;   ---system clock
       reset : in std_logic;  ---switching process
 	sda   : inout std_logic;  ----i2c data line
		scl   : out std_logic := '1'; ---i2c clock line
		l1    : out std_logic := '1');
end write;

architecture Behavioral of write is

type state is (start,state1,state2,state3,stop,finish); ---fsm
signal ps : state := start;

signal control : std_logic_vector(7 downto 0) := x"0b"; --command data for write
signal add     : std_logic_vector(7 downto 0) := x"00"; --address
signal datas    : std_logic_vector(7 downto 0) := x"00"; --initial value for second	
signal datam    : std_logic_vector(7 downto 0) := x"9a";--initial value for minutes
signal datah    : std_logic_vector(7 downto 0) := x"c4";	--initial value for hours
signal datada    : std_logic_vector(7 downto 0) := x"80"; --initial value for day
signal datadate    : std_logic_vector(7 downto 0) := x"8c";	--initial value for date
signal datamon    : std_logic_vector(7 downto 0) := x"48";	--initial value for month
signal dataye    : std_logic_vector(7 downto 0) := x"10";	--initial value for year			 
signal ack : std_logic := '1';								 
begin
process(reset,clk)------------------
variable i,j : integer := 0;
begin
if reset = '1' then
if clk'event and clk = '1' then
if ps = start then    ---i2c start condition
if i <= 250 then
i := i + 1;
sda <= '1';
scl <= '1';
elsif i > 250 and i <= 500 then
i := i + 1;
sda <= '0';
scl <= '1';
elsif i > 500 and i < 750 then
i := i + 1;
sda <= '0';
scl <= '0';
elsif i = 750 then
i := 0;
sda <= '0';
scl <= '0';
ps <= state1 ;
end if;
end if;
---------------------------------------------------------------------
if ps = state1 then   -----control word for write
if i <= 250 then
i := i + 1;
scl <= '0';
if j < 8 then
sda <= control(j);
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
if j < 8 then
sda <= control(j);
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
if j < 8 then
sda <= control(j);
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i = 750 then
scl <= '0';
i := 0;
if j < 8 then
j := j + 1;
elsif j = 8 then
j := 0;
ps <= state2;
end if;
end if;
end if;
--------------------------------------------------------
if ps = state2 then   ----address send state
if i <= 250 then
i := i + 1;
scl <= '0';
if j < 8 then
sda <= add(j);  ---sending each bit of address
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
if j < 8 then
sda <= add(j);
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
if j < 8 then
sda <= add(j);
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i = 750 then
scl <= '0';
i := 0;
if j < 8 then
j := j + 1;
elsif j = 8 then
j := 0;
case add  is    -----assigning address for each register
when x"00" =>
add <= x"80" ;
when x"80" =>
add <= x"40" ;
------------------------------------------------
when x"40" =>
add <= x"c0" ;
when x"c0" =>
add <= x"20" ;
when x"20" =>
add <= x"a0" ;
when x"a0" =>
add <= x"60" ;
when x"60" =>
add <= x"70" ;
when others =>
null;
------------------------------------------------
end case;
ps <= state3;
end if;
end if;
end if;
if ps = state3 then
if i <= 250 then
i := i + 1;
scl <= '0';
if j < 8 then
case add  is    ---assigning initial data for each register
when x"80"  =>
sda <= datas(j);
------------------------------------------------
when x"40" =>
sda <= datam(j);
when x"c0" =>
sda <= datah(j);
when x"20" =>
sda <= datada(j);
when x"a0" =>
sda <= datadate(j);
when x"60" =>
sda <= datamon(j);
when x"70" =>
sda <= dataye(j);
when others =>
null;
--------------------------------------------------
end case;
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
if j < 8 then
case add is 
when x"80"  =>
sda <= datas(j);
------------------------------------------------
when x"40" =>
sda <= datam(j);
when x"c0" =>
sda <= datah(j);
when x"20" =>
sda <= datada(j);
when x"a0" =>
sda <= datadate(j);
when x"60" =>
sda <= datamon(j);
l1 <= '0';
when x"70" =>
sda <= dataye(j);
when others =>
null;
--------------------------------------------------
end case;
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
if j < 8 then
case add is
when x"80"  =>
sda <= datas(j);
------------------------------------------------
when x"40" =>
sda <= datam(j);
when x"c0" =>
sda <= datah(j);
when x"20" =>
sda <= datada(j);
when x"a0" =>
sda <= datadate(j);
when x"60" =>
sda <= datamon(j);
when x"70" =>
sda <= dataye(j);
when others =>
null;
--------------------------------------------------
end case;
elsif j = 8 then
sda <= 'Z';
ack <= sda;
end if;
elsif i = 750 then
scl <= '0';
i := 0;
if j < 8 then
j := j + 1;
elsif j = 8 then
j := 0;
ps <= stop;
end if;
end if;
end if;
--------------------------------------------------------
if ps = stop then    ----i2c stop condition 
if i <= 250 then
i := i + 1;
sda <= '0';
scl <= '1';
elsif i > 250 and i <= 500 then
i := i + 1;
sda <= '1';
scl <= '1';
elsif i > 500 and i < 750 then
i := i + 1;
sda <= '1';
scl <= '1';
elsif i = 750 then
i := 0;
sda <= '1';
scl <= '1';
case add  is
when x"70" =>
ps <= finish ;
when x"80" =>
ps <= start ;
------------------------------------------------
when x"40" =>
ps <= start ;
when x"c0" =>
ps <= start ;
when x"20" =>
ps <= start ;
when x"a0" =>
ps <= start ;
when x"60" =>
ps <= start ;
when others =>
null;
------------------------------------------------
end case; 
end if;
-----------------------------------------
end if;
end if;
end if;
end process;
end Behavioral;

User Constraint File

NET "clk"  LOC = "p55"  ;
NET "l1"  LOC = "p14"  ;
NET "reset"  LOC = "p32"  ;
NET "scl"  LOC = "p98"  ;
NET "sda"  LOC = "p97"  ;

VHDL Code to Read Data from RTC and Display it in UART

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity read is
port ( clk   : in std_logic;               ---clock i/p
       reset : in std_logic;               ---switch i/p
	sda   : inout std_logic := '0';     ---i2c data line
	scl   : out std_logic := '0';       ---i2c clock line
	do    : out std_logic := '1';       ---uart transmit line
	l1    : out std_logic := '0');      ---led display
end read;

architecture Behavioral of read is 
type states is (start,res,dat,stop,judge,secondstata1,day,data1,final,waity);  --fsm
signal stata : states := start;
constant control1 : std_logic_vector(7 downto 0) := x"d0";  --command for write
signal add : std_logic_vector(7 downto 0) := "00000000";                       --x"01" ;
constant control2 : std_logic_vector(7 downto 0) := x"d1";	---command for read
signal stores : std_logic_vector(7 downto 0) := x"00";      --storing of second
signal storem : std_logic_vector(7 downto 0) := x"00";      --storing of minute
signal storeh : std_logic_vector(7 downto 0) := x"00";      --storing of hour
signal storeda : std_logic_vector(7 downto 0):= x"01";      --storing of day
signal storedate : std_logic_vector(7 downto 0):= x"00";    --storing of date
signal storemon : std_logic_vector(7 downto 0):= x"00";     --storing of month
signal storeye : std_logic_vector(7 downto 0):= x"00";      --storing of year
type arrss is array(0 to 30) of std_logic_vector(7 downto 0);
signal store1 : arrss :=(x"54",x"49",x"4D",x"45",x"20",x"3a",x"20",x"00",x"00",x"3a",
x"00",x"00",x"3a",x"00",x"00",x"20",x"00",x"00",x"00",x"20",x"00",x"00",x"3a",x"00",
x"00",x"3a",x"32",x"30",x"00",x"00",x"0d");		 
signal ack : std_logic;								 
begin
process(reset,clk,sda)
variable a,i,y,z : integer := 0;
variable n : integer := 7;
begin
if reset = '1' then
if clk'event and clk = '1' then
if stata = start then    ----start condition
if i <= 250 then
i := i + 1;
sda <= '1';
scl <= '1';
elsif i > 250 and i < 500 then
i := i + 1;
sda <= '0';
scl <= '1';
elsif i = 500 then
i := 0;
sda <= '0';
scl <= '0';
stata <= res ;
end if;
end if;
if stata = res then
if i <= 250 then  ----command and address send state
i := i + 1;
scl <= '0';
if n > -1 then
if a = 0 then
sda <= control1(n);   ----write command 
elsif a = 1 then
sda <= add(n);        ----address
elsif a = 2 then
sda <= control2(n);   ----read command
end if;
elsif n = -1 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
if n > -1 then
if a = 0 then
sda <= control1(n);
elsif a = 1 then
sda <= add(n);
elsif a = 2 then
sda <= control2(n);
end if;
elsif n = -1 then
sda <= 'Z';
ack <= sda;
end if;
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
if n > -1 then
if a = 0 then
sda <= control1(n);
elsif a = 1 then
sda <= add(n);
elsif a = 2 then
sda <= control2(n);
end if;
elsif n = -1 then
sda <= 'Z';
ack <= sda;
end if;
elsif i = 750 then
scl <= '0';
i := 0;
if n > -1 then
n := n - 1;
elsif n = -1 then
n := 7;
if a = 0 then
a := 1;
stata <= res;
elsif a = 1 then
a := 2; 
stata <= start;
elsif a = 2 then
a := 0 ;
stata <= dat;
end if;
----------------------------------------------------------------
end if;
end if;
end if;
if stata = dat then  ----initial data for all seven register send module
if i <= 250 then
i := i + 1;
scl <= '0';
if n > -1 then
sda <= 'Z';
elsif n = -1 then
sda <= '1';
end if;
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
if n > -1 then
sda <= 'Z';
case add is 
when x"00" =>
stores(n) <= sda;
------------------------------------------------
when x"01" =>
storem(n) <= sda;
when x"02" =>
storeh(n) <= sda;
when x"03" =>
storeda(n) <= sda;
when x"04" =>
storedate(n) <= sda;
when x"05" =>
storemon(n) <= sda;
l1 <= '1';
when x"06" =>
storeye(n) <= sda;
when others =>
null;
end case;
----------------------------------------------------
elsif n = -1 then
sda <= '1';
end if;
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
if n > -1 then
sda <= 'Z';
elsif n = -1 then
sda <= '1';
end if;
elsif i = 750 then
scl <= '0';
i := 0;
if n > -1 then
n := n - 1;
elsif n = -1 then
n := 7;
stata <= stop;
end if;
end if;
end if;
-------------------------------------------------------------------------
if stata = stop then   ------stop condition state
------------------------------------------------------------
if i <= 250 then
i := i + 1;
scl <= '1';
sda <= '0';
elsif i > 250 and i <= 500 then
i := i + 1;
scl <= '1';
sda <= '1';
elsif i > 500 and i < 750 then
i := i + 1;
scl <= '0';
sda <= '0';
elsif i = 750 then
scl <= '0';
sda <= '0';
i := 0;
stata <= judge;
end if;
end if;
------------------------------------------------
if stata = judge then   ----various flow path determination
case  add is 
when  x"00" =>                      
stata <=  start;
add <= x"01" ;
when  x"01" =>                           
stata <= start;
add <= x"02" ;
when  x"02" =>                            
stata <= start;
add <= x"03" ;
when  x"03" =>                              
stata <= start;
add <= x"04" ;
when  x"04" =>
stata <= start;
add <= x"05";
when  x"05" =>
stata  <= start;
add <= x"06";
when  x"06" =>
stata  <= secondstata1;
add <= x"00";
when others =>
null;
end case;
end if;
----------------------------------------------------------------------transmit
if stata = secondstata1 then    ---conversion of received data from i2c to ascii code
store1(13) <= "00110" & stores(6 downto 4);
store1(14) <= "0011" & stores(3 downto 0);
store1(10) <= "00110" & storem(6 downto 4);
store1(11) <= "0011" & storem(3 downto 0);
store1(7) <= "001100" & storeh(5 downto 4);
store1(8) <= "0011" & storeh(3 downto 0);
stata <= day ;
end if;
if stata = day then     ---converting the received data from i2c to days
if storeda(2 downto 0) = "001" then
store1(16) <= "01010011";
store1(17) <= "01010101";
store1(18) <= "01001110";
elsif storeda(2 downto 0) = "010" then
store1(16) <= "01001101";
store1(17) <= "01001111";
store1(18) <= "01001110";
elsif storeda(2 downto 0) = "011" then
store1(16) <= "01010100";
store1(17) <= "01010101";
store1(18) <= "01000101";
elsif storeda(2 downto 0) = "100" then
store1(16) <= "01010111";
store1(17) <= "01000101";
store1(18) <= "01000100";
elsif storeda(2 downto 0) = "101" then
store1(16) <= "01010100";
store1(17) <= "01001000";
store1(18) <= "01010101";
elsif storeda(2 downto 0) = "110" then
store1(16) <= "01000110";
store1(17) <= "01010010";
store1(18) <= "01001001";
elsif storeda(2 downto 0) = "111" then
store1(16) <= "01010010";
store1(17) <= "01000001";
store1(18) <= "01010100";
end if;
stata <= data1;
end if;
-----------------------------------------------------------------------------------
if stata = data1 then
store1(20) <= "001100" & storedate(5 downto 4);
store1(21) <= "0011"    & storedate(3 downto 0);
store1(23) <= "0011000" & storemon(4);
store1(24) <= "0011"    & storemon(3 downto 0);
store1(28) <= "0011"    &  storeye(7 downto 4);
store1(29) <= "0011"    & storeye(3 downto 0);
stata <= final;
end if;
-----------------------------------------------------------------------------------
if stata = final then
scl <= '0';
sda <= '0';
if i < 5200 then   ----timing delay for each bit in uart controller
i := i + 1;
if z = 0 then
do <= '0';
elsif z = 1 then
do <= store1(y)(0);
elsif z = 2 then
do <= store1(y)(1);
elsif z = 3 then
do <= store1(y)(2);
elsif z = 4 then
do <= store1(y)(3);
elsif z = 5 then
do <= store1(y)(4);
elsif z = 6 then
do <= store1(y)(5);
elsif z = 7 then
do <= store1(y)(6);
elsif z = 8 then
do <= store1(y)(7);
elsif z = 9 then
do <= '1';
end if;
elsif i = 5200 then
i := 0;
if z <= 8 then
z := z + 1;
elsif z > 8 then
z := 0 ;
if y < 30 then       ---14
y := y + 1;
elsif y = 30 then
y := 0;
stata  <=  waity;                                 --waity;
end if;
end if;
end if;
end if;
------------------------------------------------------------------
if stata = waity then     ---delay before reading repeatedly again the seven registers
scl <= '0';
sda <= '0';
if i < 50000000 then
i := i + 1;
elsif i = 50000000 then
i := 0 ;
stata  <= start;
end if;
end if;
-----------------------------------------------
end if;
end if;
----------------------------------------------------------
end process;

end Behavioral;

User Constraint File

NET "clk"  LOC = "p55"  ; 
NET "do"  LOC = "p12"  ; 
NET "l1"  LOC = "p14"  ;
NET "reset"  LOC = "p32"  ; 
NET "scl"  LOC = "p98"  ; 
NET "sda"  LOC = "p97"  ;