Skip to content

Commit

Permalink
Module to access MCP3008 via SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
cajt committed Feb 15, 2012
1 parent 7d153d0 commit 7ef92e7
Show file tree
Hide file tree
Showing 5 changed files with 485 additions and 0 deletions.
173 changes: 173 additions & 0 deletions fpga/modules/adc_mcp3008/hdl/adc_mcp3008.vhd
@@ -0,0 +1,173 @@
-------------------------------------------------------------------------------
-- Title : Title String
-- Project :
-------------------------------------------------------------------------------
-- File : adc_mcp3008.vhd
-- Author : Calle <calle@Alukiste>
-- Company :
-- Created : 2011-09-27
-- Last update: 2012-02-12
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- Copyright (c) 2011
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-09-27 1.0 calle Created
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.adc_mcp3008_pkg.all;

-------------------------------------------------------------------------------

entity adc_mcp3008 is

generic (
DELAY : natural := 39 -- waitstates between toggling the
-- SCK line (MCP3008 max: about 1.3 MHz)
);
port (
--adc_in.miso : in std_logic;
--adc_out.mosi : out std_logic;
--adc_out.cs_n : out std_logic;
--adc_out.sck : out std_logic;

adc_out : out adc_mcp3008_spi_out_type;
adc_in : in adc_mcp3008_spi_in_type;

start_p : in std_logic;
adc_mode_p : in std_logic;
channel_p : in std_logic_vector(2 downto 0);
value_p : out std_logic_vector(9 downto 0);
done_p : out std_logic;

reset : in std_logic;
clk : in std_logic
);

end adc_mcp3008;

-------------------------------------------------------------------------------

architecture behavioral of adc_mcp3008 is

type adc_mcp3008_state_type is (IDLE, SCK_LOW, SCK_HIGH);

type adc_mcp3008_type is record
state : adc_mcp3008_state_type;
csn : std_logic;
sck : std_logic;
din : std_logic_vector(9 downto 0);
done : std_logic;
countdown_delay : integer range 0 to DELAY;
countdown_bit : integer range 0 to 16;
dout : std_logic_vector(4 downto 0);
end record;


-----------------------------------------------------------------------------
-- Internal signal declarations
-----------------------------------------------------------------------------
signal r, rin : adc_mcp3008_type;

-----------------------------------------------------------------------------
-- Component declarations
-----------------------------------------------------------------------------

begin

seq_proc : process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
r.state <= IDLE;
r.csn <= '1';
r.sck <= '0';
r.dout <= "11111";
r.din <= (others => '0');
r.done <= '0';
r.countdown_bit <= 0;
r.countdown_delay <= DELAY;
else
r <= rin;
end if;
end if;
end process seq_proc;

adc_out.cs_n <= r.csn;
adc_out.sck <= r.sck;
adc_out.mosi <= r.dout(4);

done_p <= r.done;
value_p <= r.din;

comb_proc : process(adc_mode_p, channel_p, adc_in.miso, r, start_p)
variable v : adc_mcp3008_type;
begin
v := r;

case v.state is
when IDLE =>
v.csn := '1';
v.done := '0';
if start_p = '1' then
v.state := SCK_LOW;
v.sck := '0';

v.countdown_delay := DELAY;
v.countdown_bit := 16;
v.dout := '1' & adc_mode_p & channel_p;
end if;

when SCK_LOW =>
v.csn := '0';
if r.countdown_delay = 0 then
v.state := SCK_HIGH;
v.sck := '1';
v.countdown_delay := DELAY;
v.din := r.din(8 downto 0) & adc_in.miso; -- no need to synchronize
-- this signal, as it is
-- already in sync with
-- adc_out.sck and clk.
else
v.countdown_delay := v.countdown_delay -1;
end if;

when SCK_HIGH =>
if r.countdown_delay = 0 then
v.state := SCK_LOW;
v.sck := '0';

v.countdown_delay := DELAY;
v.dout := r.dout(3 downto 0) & '0';

if r.countdown_bit = 0 then
v.state := IDLE;
v.sck := '0';
v.done := '1';
else
v.countdown_bit := v.countdown_bit - 1;

end if;

else
v.countdown_delay := v.countdown_delay -1;
end if;

end case;

rin <= v;
end process comb_proc;

-----------------------------------------------------------------------------
-- Component instantiations
-----------------------------------------------------------------------------

end behavioral;
81 changes: 81 additions & 0 deletions fpga/modules/adc_mcp3008/hdl/adc_mcp3008_pkg.vhd
@@ -0,0 +1,81 @@
-------------------------------------------------------------------------------
-- Title : Components package (generated by Emacs VHDL Mode 3.33.6)
-- Project :
-------------------------------------------------------------------------------
-- File : components.vhd
-- Author : Calle <calle@Alukiste>
-- Company :
-- Created : 2012-02-12
-- Last update: 2012-02-12
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- Copyright (c) 2012
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2012-02-12 1.0 calle Created
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-------------------------------------------------------------------------------

package adc_mcp3008_pkg is


type adc_mcp3008_spi_out_type is record
mosi : std_logic;
cs_n : std_logic;
sck : std_logic;
end record;

type adc_mcp3008_spi_in_type is record
miso : std_logic;
end record;

-----------------------------------------------------------------------------
-- Component declarations
-----------------------------------------------------------------------------
component adc_mcp3008
generic (
DELAY : natural);
port (
adc_out : out adc_mcp3008_spi_out_type;
adc_in : in adc_mcp3008_spi_in_type;
start_p : in std_logic;
adc_mode_p : in std_logic;
channel_p : in std_logic_vector(2 downto 0);
value_p : out std_logic_vector(9 downto 0);
done_p : out std_logic;
reset : in std_logic;
clk : in std_logic);
end component;

--component adc_mcp3008
-- generic (
-- DELAY : natural);
-- port (
-- miso_p : in std_logic;
-- mosi_p : out std_logic;
-- cs_np : out std_logic;
-- sck_p : out std_logic;
-- start_p : in std_logic;
-- adc_mode_p : in std_logic;
-- channel_p : in std_logic_vector(2 downto 0);
-- value_p : out std_logic_vector(9 downto 0);
-- done_p : out std_logic;
-- reset : in std_logic;
-- clk : in std_logic);
--end component;

--component adc_mcp3008_tb
--end component;

end adc_mcp3008_pkg;

-------------------------------------------------------------------------------
26 changes: 26 additions & 0 deletions fpga/modules/adc_mcp3008/tb/Makefile
@@ -0,0 +1,26 @@

# Name of the testbench without extenstion
TESTBENCH = adc_mcp3008_tb
#TESTBENCH = enitiy_name2_tb

# VHDL files
ifeq ($(TESTBENCH), adc_mcp3008_tb)
FILES = \
../hdl/adc_mcp3008.vhd \
../hdl/adc_mcp3008_pkg.vhd
else ifeq ($(TESTBENCH), enitiy_name2_tb)
FILES = ../hdl/*.vhd
endif

# Default settings for gtkwave (visable signal etc.)
# use gtkwave > File > Write Save File (Strg + S) to generate the file
WAVEFORM_SETTINGS = $(TESTBENCH).sav

# Simulation break condition
#GHDL_SIM_OPT = --assert-level=error
GHDL_SIM_OPT = --stop-time=10us

# Load default options for GHDL.
# Defines make [all|compile|run|view|clean]
include ../../makefile.ghdl.mk

36 changes: 36 additions & 0 deletions fpga/modules/adc_mcp3008/tb/adc_mcp3008_tb.sav
@@ -0,0 +1,36 @@
[timestart] 0
[size] 1920 1004
[pos] 0 30
*-29.319311 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.adc_mcp3008_tb.
[treeopen] top.adc_mcp3008_tb.dut.
[treeopen] top.adc_mcp3008_tb.dut.r.
[treeopen] top.adc_mcp3008_tb.dut.rin.
@28
top.adc_mcp3008_tb.clk
top.adc_mcp3008_tb.reset
top.adc_mcp3008_tb.start_p
top.adc_mcp3008_tb.done_p
top.adc_mcp3008_tb.csn_p
top.adc_mcp3008_tb.sck_p
top.adc_mcp3008_tb.mosi_p
#{top.adc_mcp3008_tb.channel_p[2:0]} top.adc_mcp3008_tb.channel_p[2] top.adc_mcp3008_tb.channel_p[1] top.adc_mcp3008_tb.channel_p[0]
@c00023
#{top.adc_mcp3008_tb.value_p[9:0]} top.adc_mcp3008_tb.value_p[9] top.adc_mcp3008_tb.value_p[8] top.adc_mcp3008_tb.value_p[7] top.adc_mcp3008_tb.value_p[6] top.adc_mcp3008_tb.value_p[5] top.adc_mcp3008_tb.value_p[4] top.adc_mcp3008_tb.value_p[3] top.adc_mcp3008_tb.value_p[2] top.adc_mcp3008_tb.value_p[1] top.adc_mcp3008_tb.value_p[0]
@28
top.adc_mcp3008_tb.value_p[9]
top.adc_mcp3008_tb.value_p[8]
top.adc_mcp3008_tb.value_p[7]
top.adc_mcp3008_tb.value_p[6]
top.adc_mcp3008_tb.value_p[5]
top.adc_mcp3008_tb.value_p[4]
top.adc_mcp3008_tb.value_p[3]
top.adc_mcp3008_tb.value_p[2]
top.adc_mcp3008_tb.value_p[1]
top.adc_mcp3008_tb.value_p[0]
@1401201
-group_end
@28
top.adc_mcp3008_tb.dut.r.countdown_delay
top.adc_mcp3008_tb.miso_p

0 comments on commit 7ef92e7

Please sign in to comment.