Beginning FPGA Programming - Partie66
Beginning FPGA Programming - Partie66
In Figure 14-17 you can see that temperature_sensor_top is the top-level design. The top-level
design replaces the uartTOi2c (from the example in Chapter 13) with the uartTOi2cspi module. The new
uartTOi2cspi module is the uartTOi2c module with SPI master module (spi_master).
We are going to update the Chapter 13 design to include the Accelerometer. We will start from the
lowest-level module which is uartTOi2c. We need to update three things on this module.
1.
Add spi_master to the uartTOi2c.vhd
2.
Add new control and status registers for the UART to control the SPI master
3.
Save as a new file with a new entity name of uartTOi2cspi.vhd with the new port
list (SPI)
323
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!
Before moving on to update the design, let us show you where the accelerometer chip is on the BeMicro
MAX10. Figure 14-18 shows the back of the board and the location of the chip.
Figure 14-18. The back side of the BeMicro MAX10 with the Accelerometer
324
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!
325
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!
In Table 14-1, we defined that the register with the address 0x0000 can control the external LED and
turn it on and off. The register gets updated to control only the top six LEDs. The low two LEDs (1 and 0) are
connected to the SPI slave INT 1 and INT 2. So LED 1 and LED 0 are used to indicate the interrupts from the
Accelerometer.
The register 0x0100 is used to set up the SPI master module clock speed, polarity, and clock phase. It is
reported back to the status section.
The register 0x0101 is used to request the SPI master to send/receive one byte. Bit 31 is set to '1' to
indicate a valid request with the write value in the bit 7 to 0. If this request is the last byte to write/read, bit 8
(the last byte) also needs to be set HIGH. This register will report back to the status section too.
The register 0x0110 status reports three bytes. These three bytes are the last three times read result from
the acceleration sensor. It works like a byte shift register. On every new read request from the acceleration
sensor (register 0x0101), this register will shift left by one byte (8 bits), which means that it will show the last
three read bytes from the acceleration sensor. This three bytes read back are used to report the value of three
axis acceleration from teh Accelerometer.
The section “Example Design Codes” will show all of the foregoing updates.
■■Note Remember to select the temperature_accelerometer_sensor_top.vhd as the top entity design file in
the project before compiling the project.
entity spi_master is
port(
clk : in std_logic; --system clock
reset_n : in std_logic; --active low reset
clk_div : in std_logic_vector(15 downto 0); -- spi_sclk = clk/(clk_div x 2)
cspol : in std_logic; -- chip select polarity (0 = active low)
cpha : in std_logic;
cpol : in std_logic;
ena : in std_logic;
write_byte : in std_logic_vector(7 downto 0);
326
Chapter 14 ■ How Fast Can You Run? Ask the Accelerometer!
last_byte : in std_logic;
read_byte : out std_logic_vector(7 downto 0);
done : out std_logic;
spi_sclk : out std_logic; -- run in 230kHz
spi_cs : out std_logic;
spi_mosi : out std_logic;
spi_miso : in std_logic
);
end spi_master;
clk_div2 <= unsigned(clk_div) & '0'; -- double the clk_div value to clk_div2
--generate the timing for the spi clock (spi_sclk) and the data clock (data_clk)
clk_gen_p : process(clk, reset_n)
begin
if(reset_n = '0') then --reset asserted
count <= (others => '0');
spi_sclk <= '0';
data_clk <= '0';
elsif rising_edge(clk) then
if(count = clk_div2-1) then --end of timing cycle
count <= (others => '0'); --reset timer
else
count <= count + 1; --continue clock generation timing
end if;
327