Beginning FPGA Programming - Partie68

Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!

-- Generate a ena pulse for SPI Master


reg_spi_write(31) <= '0';

end if;
end if;
end process;

i2c_data_p : process (s_rst, s_clk_uart)


begin
if s_rst = '1' then
reg02(29 downto 0) <= (others => '0');
elsif rising_edge(s_clk_uart) then
-- when the busy is change from 1 to 0
if(i2c_busy = '0' and i2c_busy_dly = '1') then
-- copy the I2C data_rd to reg02(7 downto 0)
-- and copy reg02(7 downto 0) to reg02(15 downto 0)
reg02(15 downto 0) <= reg02(7 downto 0) & data_rd;
end if;
-- bit 15 to 3 is the 13 bit temperature
-- each 1 equal 0.0625 and 0x0 equal to 0'C
-- Only need bit 15 to 7 to read out in integer
-- shift bits to upper bytes for easy read in degree C
reg02(24 downto 16) <= reg02(15 downto 7);

end if;
end process;

spi_data_p : process (s_rst, s_clk_uart)


begin
if s_rst = '1' then
reg_spi_read <= (others => '0');
spi_firstbyte <= '1';
elsif rising_edge(s_clk_uart) then
spi_done_dly <= spi_done;
if(spi_done = '1' and spi_done_dly = '0') then
if(spi_firstbyte = '1') then -- First byte
reg_spi_read(31 downto 8) <= (others => '0');
reg_spi_read(7 downto 0) <= spi_read;
else
reg_spi_read <= reg_spi_read(23 downto 0) & spi_read;
end if;

if(reg_spi_write(8) = '1') then -- last byte


spi_firstbyte <= '1'; -- ready for next spi read as first byte
else
spi_firstbyte <= '0';
end if;
end if;

end if;
end process;

333
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!

register_update : process (s_rst, s_clk_uart)


variable v_uart_tx_add : unsigned (15 downto 0);
variable v_count : unsigned (15 downto 0);
begin
if s_rst = '1' then -- reset all registers here
s_uart_tx_data_rdy <= '0';
s_uart_tx_req <= '0';
v_uart_tx_add := (others => '0');
v_count := (others => '0');
s_uart_tx_data <= (others => '0');
s_uart_tx_add <= (others => '0');
s_tx_fsm <= IDLE;
elsif rising_edge(s_clk_uart) then
case s_tx_fsm is
when IDLE =>
if s_update = '1' then
s_tx_fsm <= WAIT_A_BYTE;
else
s_tx_fsm <= IDLE;
s_uart_tx_data_rdy <= '0';
s_uart_tx_req <= '0';
v_uart_tx_add := (others => '0');
v_count := (others => '0');
s_uart_tx_data <= (others => '0');
s_uart_tx_add <= (others => '0');
end if;
when WAIT_A_BYTE =>
s_uart_tx_data_rdy <= '0';
v_count := v_count + 1;
if v_count = X"0900" then
v_uart_tx_add := v_uart_tx_add + 1;
s_tx_fsm <= LATCH;
else
s_tx_fsm <= WAIT_A_BYTE;
end if;
when LATCH =>
if s_uart_tx_stb_acq = '0' then
s_uart_tx_req <= '1';
s_uart_tx_add <= std_logic_vector (v_uart_tx_add);
case v_uart_tx_add is
when X"0001" => s_uart_tx_data (7 downto 0) <= r_leds;
s_tx_fsm <= TRANSMIT;
-- #####################
-- declare more registers here to READ
-- #####################
when X"0010" => s_uart_tx_data <= reg01;
s_tx_fsm <= TRANSMIT;
when X"0011" => s_uart_tx_data <= reg02;
s_tx_fsm <= TRANSMIT;
when X"0100" => s_uart_tx_data <= reg_spi_control;
s_tx_fsm <= TRANSMIT;

334
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!

when X"0101" => s_uart_tx_data <= reg_spi_write;


s_tx_fsm <= TRANSMIT;
when X"0102" => s_uart_tx_data <= reg_spi_read;
s_tx_fsm <= TRANSMIT;
-- End Of Transmission register = last register + 1
when X"0103" => s_tx_fsm <= IDLE; -- end of transmission
when others => s_uart_tx_data <= (others => '0');
v_uart_tx_add := v_uart_tx_add + 1;
s_uart_tx_data_rdy <= '0';
s_tx_fsm <= LATCH;
end case;
else
v_count := (others => '0');
s_tx_fsm <= WAIT_A_BYTE;
end if;
when TRANSMIT =>
s_uart_tx_data_rdy <= '1';
v_count := (others => '0');
s_tx_fsm <= WAIT_A_BYTE;
when others =>
s_tx_fsm <= IDLE;
end case;
end if;
end process;

uart_wrapper : entity work.uart_16550_wrapper


port map(
sys_clk_i => s_clk_uart,
sys_rst_i => s_rst,
echo_en_i => r_config_addr_uart(0),
tx_addr_wwo_i => r_config_addr_uart(1),
uart_din_i => uart_din_i,
uart_dout_o => uart_dout_o,
s_br_clk_uart_o => s_uart_br_clk,
v_rx_add_o => s_uart_rx_add,
v_rx_data_o => s_uart_rx_data,
s_rx_rdy_o => s_uart_rx_rdy,
s_rx_stb_read_data_i => s_uart_rx_stb_read_data,
s_tx_proc_rqst_i => s_uart_tx_req,
v_tx_add_ram_i => s_uart_tx_add,
v_tx_data_ram_i => s_uart_tx_data,
s_tx_ram_data_rdy_i => s_uart_tx_data_rdy,
s_tx_stb_ram_data_acq_o => s_uart_tx_stb_acq
);

i2cM_p : entity work.i2c_master


generic map(
input_clk => 29_491_200, --input clock speed from user logic in Hz
bus_clk => 100_000) --speed the i2c bus (scl) will run at in Hz
port map(
clk => s_clk_uart, --system clock

335
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!

reset_n => s_rst_n, --active low reset


ena => reg01(31), --latch in command
addr => reg01(22 downto 16), --address of target slave
rw => reg01(23), --'0' is write, '1' is read
data_wr => data_wr, --data to write to slave
busy => i2c_busy, --indicates transaction in progress
data_rd => data_rd, --data read from slave
ack_error => reg02(30), --flag if improper acknowledge from slave
sda => i2c_dat, --serial data output of i2c bus
scl => i2c_scl); --serial clock output of i2c bus

spiM_p : entity work.spi_master


port map(
clk => s_clk_uart,
reset_n => s_rst_n,
clk_div => reg_spi_control(15 downto 0),
cspol => reg_spi_control(16), -- chip select polarity (0 = active low)
cpha => reg_spi_control(21),
cpol => reg_spi_control(22),
ena => reg_spi_write(31),
write_byte => reg_spi_write(7 downto 0),
last_byte => reg_spi_write(8),
read_byte => spi_read,
done => spi_done,
spi_sclk => spi_sclk, -- run in 230kHz
spi_cs => spi_csn,
spi_mosi => spi_mosi,
spi_miso => spi_miso);

end architecture rtl;

14.3.3.3 Temperature_accelerometer_sensor_top.vhd Code
The code in Listing 14-3 is the top-level design file for this project. It has the system clock (50 MHz) input and
ADT7420 IC interfaces which include I2C SCL and SDA wires. The USER_LED is included for fun. The purpose
of this module is to connect all of the external wires to the correct modules and to generate the correct clock
(29.5 MHz) for the uartTOi2c module. Please read the comments to better understand the details of the design.
We will simulate the design later and so you should have a better idea how it works after that.

Listing 14-3.  Temperature Sensor Top-Level Design VHDL File


library ieee;
use ieee.std_logic_1164.all;

entity temperature_accelerometer_sensor_top is
port(
-- Clock ins, SYS_CLK = 50MHz
SYS_CLK : in std_logic;

-- Temperature sensor, I2C interface (ADT7420)

336
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!

ADT7420_CT : in std_logic; -- NOT USE


ADT7420_INT : in std_logic; -- NOT USE
ADT7420_SCL : inout std_logic;
ADT7420_SDA : inout std_logic;
-- The following is added for chapter 14 SPI interface
-- Accelerometer, 3-Axis, SPI interface (ADXL362)
ADXL362_CS : out std_logic;
ADXL362_INT1 : in std_logic;
ADXL362_INT2 : in std_logic;
ADXL362_MISO : in std_logic;
ADXL362_MOSI : out std_logic;
ADXL362_SCLK : out std_logic;
-- LED outs
USER_LED : out std_logic_vector(8 downto 1);

GPIO_J3_39 : out std_logic; -- UART TX


GPIO_J3_40 : in std_logic -- UART RX
);

end entity temperature_ ACCELEROMETER_sensor_top;

architecture arch of temperature_ ACCELEROMETER_sensor_top is

signal locked, clk_uart_29MHz_i, uart_rst_i : std_logic:= '0';


signal delay_8: std_logic_vector(7 downto 0);

begin

clk : entity work.pll_29p5M


port map
(
inclk0 => SYS_CLK, -- 50MHz clock input
c0 => clk_uart_29MHz_i,-- 29.5MHz clock ouput
locked => locked -- Lock condition, 1 = Locked
);

dealy_p: process(SYS_CLK)
begin
if(rising_edge(SYS_CLK) )THEN
delay_8 <= delay_8(6 downto 0)&locked; -- create active LOW reset
END IF;
END PROCESS;

uart_rst_i <= delay_8(7);


-- Replace the module uartTOi2c with uartTOi2cspi for chapter 14
uartTOi2c_pm : entity work.uartTOi2cspi
port map(
clk_uart_29MHz_i => clk_uart_29MHz_i,
uart_rst_i => uart_rst_i,
uart_leds_o => USER_LED,
clk_uart_monitor_o => open,

337

You might also like