Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Module to access MCP3008 via SPI

  • Loading branch information...
commit 7ef92e74fdb1af6c220e5deb1a04a36c8303aa1d 1 parent 7d153d0
cajt cajt authored
173 fpga/modules/adc_mcp3008/hdl/adc_mcp3008.vhd
... ... @@ -0,0 +1,173 @@
  1 +-------------------------------------------------------------------------------
  2 +-- Title : Title String
  3 +-- Project :
  4 +-------------------------------------------------------------------------------
  5 +-- File : adc_mcp3008.vhd
  6 +-- Author : Calle <calle@Alukiste>
  7 +-- Company :
  8 +-- Created : 2011-09-27
  9 +-- Last update: 2012-02-12
  10 +-- Platform :
  11 +-- Standard : VHDL'87
  12 +-------------------------------------------------------------------------------
  13 +-- Description:
  14 +-------------------------------------------------------------------------------
  15 +-- Copyright (c) 2011
  16 +-------------------------------------------------------------------------------
  17 +-- Revisions :
  18 +-- Date Version Author Description
  19 +-- 2011-09-27 1.0 calle Created
  20 +-------------------------------------------------------------------------------
  21 +
  22 +library ieee;
  23 +use ieee.std_logic_1164.all;
  24 +use ieee.numeric_std.all;
  25 +
  26 +use work.adc_mcp3008_pkg.all;
  27 +
  28 +-------------------------------------------------------------------------------
  29 +
  30 +entity adc_mcp3008 is
  31 +
  32 + generic (
  33 + DELAY : natural := 39 -- waitstates between toggling the
  34 + -- SCK line (MCP3008 max: about 1.3 MHz)
  35 + );
  36 + port (
  37 + --adc_in.miso : in std_logic;
  38 + --adc_out.mosi : out std_logic;
  39 + --adc_out.cs_n : out std_logic;
  40 + --adc_out.sck : out std_logic;
  41 +
  42 + adc_out : out adc_mcp3008_spi_out_type;
  43 + adc_in : in adc_mcp3008_spi_in_type;
  44 +
  45 + start_p : in std_logic;
  46 + adc_mode_p : in std_logic;
  47 + channel_p : in std_logic_vector(2 downto 0);
  48 + value_p : out std_logic_vector(9 downto 0);
  49 + done_p : out std_logic;
  50 +
  51 + reset : in std_logic;
  52 + clk : in std_logic
  53 + );
  54 +
  55 +end adc_mcp3008;
  56 +
  57 +-------------------------------------------------------------------------------
  58 +
  59 +architecture behavioral of adc_mcp3008 is
  60 +
  61 + type adc_mcp3008_state_type is (IDLE, SCK_LOW, SCK_HIGH);
  62 +
  63 + type adc_mcp3008_type is record
  64 + state : adc_mcp3008_state_type;
  65 + csn : std_logic;
  66 + sck : std_logic;
  67 + din : std_logic_vector(9 downto 0);
  68 + done : std_logic;
  69 + countdown_delay : integer range 0 to DELAY;
  70 + countdown_bit : integer range 0 to 16;
  71 + dout : std_logic_vector(4 downto 0);
  72 + end record;
  73 +
  74 +
  75 + -----------------------------------------------------------------------------
  76 + -- Internal signal declarations
  77 + -----------------------------------------------------------------------------
  78 + signal r, rin : adc_mcp3008_type;
  79 +
  80 + -----------------------------------------------------------------------------
  81 + -- Component declarations
  82 + -----------------------------------------------------------------------------
  83 +
  84 +begin
  85 +
  86 + seq_proc : process(clk)
  87 + begin
  88 + if rising_edge(clk) then
  89 + if reset = '1' then
  90 + r.state <= IDLE;
  91 + r.csn <= '1';
  92 + r.sck <= '0';
  93 + r.dout <= "11111";
  94 + r.din <= (others => '0');
  95 + r.done <= '0';
  96 + r.countdown_bit <= 0;
  97 + r.countdown_delay <= DELAY;
  98 + else
  99 + r <= rin;
  100 + end if;
  101 + end if;
  102 + end process seq_proc;
  103 +
  104 + adc_out.cs_n <= r.csn;
  105 + adc_out.sck <= r.sck;
  106 + adc_out.mosi <= r.dout(4);
  107 +
  108 + done_p <= r.done;
  109 + value_p <= r.din;
  110 +
  111 + comb_proc : process(adc_mode_p, channel_p, adc_in.miso, r, start_p)
  112 + variable v : adc_mcp3008_type;
  113 + begin
  114 + v := r;
  115 +
  116 + case v.state is
  117 + when IDLE =>
  118 + v.csn := '1';
  119 + v.done := '0';
  120 + if start_p = '1' then
  121 + v.state := SCK_LOW;
  122 + v.sck := '0';
  123 +
  124 + v.countdown_delay := DELAY;
  125 + v.countdown_bit := 16;
  126 + v.dout := '1' & adc_mode_p & channel_p;
  127 + end if;
  128 +
  129 + when SCK_LOW =>
  130 + v.csn := '0';
  131 + if r.countdown_delay = 0 then
  132 + v.state := SCK_HIGH;
  133 + v.sck := '1';
  134 + v.countdown_delay := DELAY;
  135 + v.din := r.din(8 downto 0) & adc_in.miso; -- no need to synchronize
  136 + -- this signal, as it is
  137 + -- already in sync with
  138 + -- adc_out.sck and clk.
  139 + else
  140 + v.countdown_delay := v.countdown_delay -1;
  141 + end if;
  142 +
  143 + when SCK_HIGH =>
  144 + if r.countdown_delay = 0 then
  145 + v.state := SCK_LOW;
  146 + v.sck := '0';
  147 +
  148 + v.countdown_delay := DELAY;
  149 + v.dout := r.dout(3 downto 0) & '0';
  150 +
  151 + if r.countdown_bit = 0 then
  152 + v.state := IDLE;
  153 + v.sck := '0';
  154 + v.done := '1';
  155 + else
  156 + v.countdown_bit := v.countdown_bit - 1;
  157 +
  158 + end if;
  159 +
  160 + else
  161 + v.countdown_delay := v.countdown_delay -1;
  162 + end if;
  163 +
  164 + end case;
  165 +
  166 + rin <= v;
  167 + end process comb_proc;
  168 +
  169 + -----------------------------------------------------------------------------
  170 + -- Component instantiations
  171 + -----------------------------------------------------------------------------
  172 +
  173 +end behavioral;
81 fpga/modules/adc_mcp3008/hdl/adc_mcp3008_pkg.vhd
... ... @@ -0,0 +1,81 @@
  1 +-------------------------------------------------------------------------------
  2 +-- Title : Components package (generated by Emacs VHDL Mode 3.33.6)
  3 +-- Project :
  4 +-------------------------------------------------------------------------------
  5 +-- File : components.vhd
  6 +-- Author : Calle <calle@Alukiste>
  7 +-- Company :
  8 +-- Created : 2012-02-12
  9 +-- Last update: 2012-02-12
  10 +-- Platform :
  11 +-- Standard : VHDL'87
  12 +-------------------------------------------------------------------------------
  13 +-- Description:
  14 +-------------------------------------------------------------------------------
  15 +-- Copyright (c) 2012
  16 +-------------------------------------------------------------------------------
  17 +-- Revisions :
  18 +-- Date Version Author Description
  19 +-- 2012-02-12 1.0 calle Created
  20 +-------------------------------------------------------------------------------
  21 +
  22 +library ieee;
  23 +use ieee.std_logic_1164.all;
  24 +use ieee.numeric_std.all;
  25 +
  26 +-------------------------------------------------------------------------------
  27 +
  28 +package adc_mcp3008_pkg is
  29 +
  30 +
  31 + type adc_mcp3008_spi_out_type is record
  32 + mosi : std_logic;
  33 + cs_n : std_logic;
  34 + sck : std_logic;
  35 + end record;
  36 +
  37 + type adc_mcp3008_spi_in_type is record
  38 + miso : std_logic;
  39 + end record;
  40 +
  41 + -----------------------------------------------------------------------------
  42 + -- Component declarations
  43 + -----------------------------------------------------------------------------
  44 + component adc_mcp3008
  45 + generic (
  46 + DELAY : natural);
  47 + port (
  48 + adc_out : out adc_mcp3008_spi_out_type;
  49 + adc_in : in adc_mcp3008_spi_in_type;
  50 + start_p : in std_logic;
  51 + adc_mode_p : in std_logic;
  52 + channel_p : in std_logic_vector(2 downto 0);
  53 + value_p : out std_logic_vector(9 downto 0);
  54 + done_p : out std_logic;
  55 + reset : in std_logic;
  56 + clk : in std_logic);
  57 + end component;
  58 +
  59 + --component adc_mcp3008
  60 + -- generic (
  61 + -- DELAY : natural);
  62 + -- port (
  63 + -- miso_p : in std_logic;
  64 + -- mosi_p : out std_logic;
  65 + -- cs_np : out std_logic;
  66 + -- sck_p : out std_logic;
  67 + -- start_p : in std_logic;
  68 + -- adc_mode_p : in std_logic;
  69 + -- channel_p : in std_logic_vector(2 downto 0);
  70 + -- value_p : out std_logic_vector(9 downto 0);
  71 + -- done_p : out std_logic;
  72 + -- reset : in std_logic;
  73 + -- clk : in std_logic);
  74 + --end component;
  75 +
  76 + --component adc_mcp3008_tb
  77 + --end component;
  78 +
  79 +end adc_mcp3008_pkg;
  80 +
  81 +-------------------------------------------------------------------------------
26 fpga/modules/adc_mcp3008/tb/Makefile
... ... @@ -0,0 +1,26 @@
  1 +
  2 +# Name of the testbench without extenstion
  3 +TESTBENCH = adc_mcp3008_tb
  4 +#TESTBENCH = enitiy_name2_tb
  5 +
  6 +# VHDL files
  7 +ifeq ($(TESTBENCH), adc_mcp3008_tb)
  8 +FILES = \
  9 +../hdl/adc_mcp3008.vhd \
  10 +../hdl/adc_mcp3008_pkg.vhd
  11 +else ifeq ($(TESTBENCH), enitiy_name2_tb)
  12 +FILES = ../hdl/*.vhd
  13 +endif
  14 +
  15 +# Default settings for gtkwave (visable signal etc.)
  16 +# use gtkwave > File > Write Save File (Strg + S) to generate the file
  17 +WAVEFORM_SETTINGS = $(TESTBENCH).sav
  18 +
  19 +# Simulation break condition
  20 +#GHDL_SIM_OPT = --assert-level=error
  21 +GHDL_SIM_OPT = --stop-time=10us
  22 +
  23 +# Load default options for GHDL.
  24 +# Defines make [all|compile|run|view|clean]
  25 +include ../../makefile.ghdl.mk
  26 +
36 fpga/modules/adc_mcp3008/tb/adc_mcp3008_tb.sav
... ... @@ -0,0 +1,36 @@
  1 +[timestart] 0
  2 +[size] 1920 1004
  3 +[pos] 0 30
  4 +*-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
  5 +[treeopen] top.
  6 +[treeopen] top.adc_mcp3008_tb.
  7 +[treeopen] top.adc_mcp3008_tb.dut.
  8 +[treeopen] top.adc_mcp3008_tb.dut.r.
  9 +[treeopen] top.adc_mcp3008_tb.dut.rin.
  10 +@28
  11 +top.adc_mcp3008_tb.clk
  12 +top.adc_mcp3008_tb.reset
  13 +top.adc_mcp3008_tb.start_p
  14 +top.adc_mcp3008_tb.done_p
  15 +top.adc_mcp3008_tb.csn_p
  16 +top.adc_mcp3008_tb.sck_p
  17 +top.adc_mcp3008_tb.mosi_p
  18 +#{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]
  19 +@c00023
  20 +#{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]
  21 +@28
  22 +top.adc_mcp3008_tb.value_p[9]
  23 +top.adc_mcp3008_tb.value_p[8]
  24 +top.adc_mcp3008_tb.value_p[7]
  25 +top.adc_mcp3008_tb.value_p[6]
  26 +top.adc_mcp3008_tb.value_p[5]
  27 +top.adc_mcp3008_tb.value_p[4]
  28 +top.adc_mcp3008_tb.value_p[3]
  29 +top.adc_mcp3008_tb.value_p[2]
  30 +top.adc_mcp3008_tb.value_p[1]
  31 +top.adc_mcp3008_tb.value_p[0]
  32 +@1401201
  33 +-group_end
  34 +@28
  35 +top.adc_mcp3008_tb.dut.r.countdown_delay
  36 +top.adc_mcp3008_tb.miso_p
169 fpga/modules/adc_mcp3008/tb/adc_mcp3008_tb.vhd
... ... @@ -0,0 +1,169 @@
  1 +-------------------------------------------------------------------------------
  2 +-- Title : Testbench for design "adc_mcp3008"
  3 +-- Project :
  4 +-------------------------------------------------------------------------------
  5 +-- File : adc_mcp3008_tb.vhd
  6 +-- Author : Calle <calle@Alukiste>
  7 +-- Company :
  8 +-- Created : 2012-02-11
  9 +-- Last update: 2012-02-12
  10 +-- Platform :
  11 +-- Standard : VHDL'87
  12 +-------------------------------------------------------------------------------
  13 +-- Description:
  14 +-------------------------------------------------------------------------------
  15 +-- Copyright (c) 2012
  16 +-------------------------------------------------------------------------------
  17 +-- Revisions :
  18 +-- Date Version Author Description
  19 +-- 2012-02-11 1.0 calle Created
  20 +-------------------------------------------------------------------------------
  21 +
  22 +library ieee;
  23 +use ieee.std_logic_1164.all;
  24 +
  25 +-------------------------------------------------------------------------------
  26 +
  27 +entity adc_mcp3008_tb is
  28 +
  29 +end adc_mcp3008_tb;
  30 +
  31 +-------------------------------------------------------------------------------
  32 +
  33 +architecture tb of adc_mcp3008_tb is
  34 +
  35 + use work.adc_mcp3008_pkg.all;
  36 +
  37 + -- Component generics
  38 + constant DELAY : natural := 5;
  39 +
  40 + -- component ports
  41 + signal miso_p : std_logic;
  42 + signal mosi_p : std_logic;
  43 + signal cs_np : std_logic;
  44 + signal sck_p : std_logic;
  45 + signal start_p : std_logic;
  46 + signal adc_mode_p : std_logic;
  47 + signal channel_p : std_logic_vector(2 downto 0);
  48 + signal value_p : std_logic_vector(9 downto 0);
  49 + signal done_p : std_logic;
  50 + signal reset : std_logic;
  51 +
  52 + signal adc_i : adc_mcp3008_spi_in_type;
  53 + signal adc_o : adc_mcp3008_spi_out_type;
  54 +
  55 + --signal clk : std_logic;
  56 +
  57 + -- clock
  58 + signal Clk : std_logic := '1';
  59 +
  60 +begin -- tb
  61 +
  62 + -- component instantiation
  63 + DUT : adc_mcp3008
  64 + generic map (
  65 + DELAY => 5)
  66 + port map (
  67 + adc_out => adc_o,
  68 + adc_in => adc_i,
  69 + start_p => start_p,
  70 + adc_mode_p => adc_mode_p,
  71 + channel_p => channel_p,
  72 + value_p => value_p,
  73 + done_p => done_p,
  74 + reset => reset,
  75 + clk => clk);
  76 +
  77 +
  78 + adc_i.miso <= miso_p;
  79 + mosi_p <= adc_o.mosi;
  80 + cs_np <= adc_o.cs_n;
  81 + sck_p <= adc_o.sck;
  82 +
  83 + -- clock generation
  84 + Clk <= not Clk after 10 ns;
  85 +
  86 + process
  87 + begin
  88 + reset <= '1';
  89 + wait for 22 ns;
  90 + reset <= '0';
  91 + wait for 1 ms;
  92 + end process;
  93 +
  94 +
  95 + -- waveform generation
  96 + WaveGen_Proc : process
  97 + begin
  98 + -- insert signal assignments here
  99 + start_p <= '0';
  100 + adc_mode_p <= '1';
  101 + channel_p <= "011";
  102 + wait until Clk = '1';
  103 + wait until Clk = '1';
  104 + wait until Clk = '1';
  105 + start_p <= '1';
  106 + wait until Clk = '1';
  107 + start_p <= '0';
  108 + wait until Clk = '1';
  109 +
  110 + wait for 1 ms;
  111 + end process WaveGen_Proc;
  112 +
  113 +
  114 + process
  115 + begin
  116 + miso_p <= 'Z';
  117 +
  118 + wait until cs_np = '0';
  119 +
  120 + wait until sck_p = '1';
  121 + wait until sck_p = '0';
  122 + wait until sck_p = '0';
  123 + wait until sck_p = '0';
  124 + wait until sck_p = '0';
  125 + wait until sck_p = '0';
  126 + wait until sck_p = '0';
  127 +
  128 + -- leading zero of mcp3008
  129 + miso_p <= '0';
  130 + wait until sck_p = '0';
  131 +
  132 + -- actual MSB of conversion
  133 + miso_p <= '1';
  134 + wait until sck_p = '0';
  135 + miso_p <= '0';
  136 + wait until sck_p = '0';
  137 + miso_p <= '1';
  138 + wait until sck_p = '0';
  139 + miso_p <= '0';
  140 + wait until sck_p = '0';
  141 + miso_p <= '1';
  142 + wait until sck_p = '0';
  143 + miso_p <= '0';
  144 + wait until sck_p = '0';
  145 + miso_p <= '0';
  146 + wait until sck_p = '0';
  147 + miso_p <= '1';
  148 + wait until sck_p = '0';
  149 + miso_p <= '0';
  150 + wait until sck_p = '0';
  151 + miso_p <= '1';
  152 +
  153 + wait until sck_p = '0';
  154 + miso_p <= 'Z';
  155 +
  156 + wait for 1 ms;
  157 + end process;
  158 +
  159 +
  160 +end tb;
  161 +
  162 +-------------------------------------------------------------------------------
  163 +
  164 +configuration adc_mcp3008_tb_tb_cfg of adc_mcp3008_tb is
  165 + for tb
  166 + end for;
  167 +end adc_mcp3008_tb_tb_cfg;
  168 +
  169 +-------------------------------------------------------------------------------

0 comments on commit 7ef92e7

Please sign in to comment.
Something went wrong with that request. Please try again.