Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Module to access MCP3008 via SPI

  • Loading branch information...
commit 7ef92e74fdb1af6c220e5deb1a04a36c8303aa1d 1 parent 7d153d0
@cajt cajt authored
View
173 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;
View
81 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;
+
+-------------------------------------------------------------------------------
View
26 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
+
View
36 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
View
169 fpga/modules/adc_mcp3008/tb/adc_mcp3008_tb.vhd
@@ -0,0 +1,169 @@
+-------------------------------------------------------------------------------
+-- Title : Testbench for design "adc_mcp3008"
+-- Project :
+-------------------------------------------------------------------------------
+-- File : adc_mcp3008_tb.vhd
+-- Author : Calle <calle@Alukiste>
+-- Company :
+-- Created : 2012-02-11
+-- Last update: 2012-02-12
+-- Platform :
+-- Standard : VHDL'87
+-------------------------------------------------------------------------------
+-- Description:
+-------------------------------------------------------------------------------
+-- Copyright (c) 2012
+-------------------------------------------------------------------------------
+-- Revisions :
+-- Date Version Author Description
+-- 2012-02-11 1.0 calle Created
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+-------------------------------------------------------------------------------
+
+entity adc_mcp3008_tb is
+
+end adc_mcp3008_tb;
+
+-------------------------------------------------------------------------------
+
+architecture tb of adc_mcp3008_tb is
+
+ use work.adc_mcp3008_pkg.all;
+
+ -- Component generics
+ constant DELAY : natural := 5;
+
+ -- component ports
+ signal miso_p : std_logic;
+ signal mosi_p : std_logic;
+ signal cs_np : std_logic;
+ signal sck_p : std_logic;
+ signal start_p : std_logic;
+ signal adc_mode_p : std_logic;
+ signal channel_p : std_logic_vector(2 downto 0);
+ signal value_p : std_logic_vector(9 downto 0);
+ signal done_p : std_logic;
+ signal reset : std_logic;
+
+ signal adc_i : adc_mcp3008_spi_in_type;
+ signal adc_o : adc_mcp3008_spi_out_type;
+
+ --signal clk : std_logic;
+
+ -- clock
+ signal Clk : std_logic := '1';
+
+begin -- tb
+
+ -- component instantiation
+ DUT : adc_mcp3008
+ generic map (
+ DELAY => 5)
+ port map (
+ adc_out => adc_o,
+ adc_in => adc_i,
+ start_p => start_p,
+ adc_mode_p => adc_mode_p,
+ channel_p => channel_p,
+ value_p => value_p,
+ done_p => done_p,
+ reset => reset,
+ clk => clk);
+
+
+ adc_i.miso <= miso_p;
+ mosi_p <= adc_o.mosi;
+ cs_np <= adc_o.cs_n;
+ sck_p <= adc_o.sck;
+
+ -- clock generation
+ Clk <= not Clk after 10 ns;
+
+ process
+ begin
+ reset <= '1';
+ wait for 22 ns;
+ reset <= '0';
+ wait for 1 ms;
+ end process;
+
+
+ -- waveform generation
+ WaveGen_Proc : process
+ begin
+ -- insert signal assignments here
+ start_p <= '0';
+ adc_mode_p <= '1';
+ channel_p <= "011";
+ wait until Clk = '1';
+ wait until Clk = '1';
+ wait until Clk = '1';
+ start_p <= '1';
+ wait until Clk = '1';
+ start_p <= '0';
+ wait until Clk = '1';
+
+ wait for 1 ms;
+ end process WaveGen_Proc;
+
+
+ process
+ begin
+ miso_p <= 'Z';
+
+ wait until cs_np = '0';
+
+ wait until sck_p = '1';
+ wait until sck_p = '0';
+ wait until sck_p = '0';
+ wait until sck_p = '0';
+ wait until sck_p = '0';
+ wait until sck_p = '0';
+ wait until sck_p = '0';
+
+ -- leading zero of mcp3008
+ miso_p <= '0';
+ wait until sck_p = '0';
+
+ -- actual MSB of conversion
+ miso_p <= '1';
+ wait until sck_p = '0';
+ miso_p <= '0';
+ wait until sck_p = '0';
+ miso_p <= '1';
+ wait until sck_p = '0';
+ miso_p <= '0';
+ wait until sck_p = '0';
+ miso_p <= '1';
+ wait until sck_p = '0';
+ miso_p <= '0';
+ wait until sck_p = '0';
+ miso_p <= '0';
+ wait until sck_p = '0';
+ miso_p <= '1';
+ wait until sck_p = '0';
+ miso_p <= '0';
+ wait until sck_p = '0';
+ miso_p <= '1';
+
+ wait until sck_p = '0';
+ miso_p <= 'Z';
+
+ wait for 1 ms;
+ end process;
+
+
+end tb;
+
+-------------------------------------------------------------------------------
+
+configuration adc_mcp3008_tb_tb_cfg of adc_mcp3008_tb is
+ for tb
+ end for;
+end adc_mcp3008_tb_tb_cfg;
+
+-------------------------------------------------------------------------------

0 comments on commit 7ef92e7

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