if RX = "0111111111" then
tx_pwm <= "11";
elsif RX = "000000000" then
tx_pwm <= "00";
else
tx_pwm <= "10";
end if;
Code:SPI_state: process(newClock) begin if falling_edge(newClock) then case state is when start => debug_TX <= "00000001"; CS <= '1'; MOSI <= '0'; RX <= "0000000000"; state <= state2; when state2 => -- Send init bits. CS <= '0'; shift_counter <= shift_counter - 1; TX <= TX(N-1 downto 0) & TX(N); MOSI <= TX(N); if shift_counter = 0 then MOSI <= '0'; shift_counter<= 10; state <= state3; end if; when state3 => MOSI <= '0'; CS <= '0'; -- Last bit init bit; state <= state4; when state4=> CS <= '0'; --T_sample from falling - falling state <= state6; when state6=> CS <= '0'; -- Read shift_counter <= shift_counter - 1; RX <= RX(8 downto 0) & MISO; if shift_counter = 0 then MOSI <= '0'; shift_counter<= N; state <= start; end if; when others => state <= start; end case; end if; end process;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_logic_unsigned.all;
use ieee.numeric_std.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity main is
Port ( MISO : in STD_LOGIC;
MOSI : out STD_LOGIC;
CS : out STD_LOGIC;
SCLK : out STD_LOGIC;
CLK : in STD_LOGIC;
debug_TX: out std_logic_vector(3 downto 0);
tx_pwm: out std_logic_vector(1 downto 0);
work: out std_logic;
rx_led: out std_logic_vector(9 downto 0)
);
end main;
architecture Behavioral of main is
--signal prescaler : integer range 0 to 3500000 := 3500000 ;
constant N : integer := 4;
signal prescaler_counter : integer range 0 to 50000000 := 0;
signal newClock : std_logic := '0';
signal TX :std_logic_vector(N downto 0) := "11000";
signal RX : std_logic_vector(9 downto 0) := "0000000000";
type state_type is (start,state2,state3,state5); --type of state machine.
type TXRX is (waiting, working);
signal state : state_type := start;
signal busy: std_logic:= '0';
signal shift_counter: integer range 0 to 750:= N;
begin
prescaler01: process(clk, newClock)
begin
if rising_edge(clk) then
if prescaler_counter < 5000000 then -- 14
prescaler_counter <= prescaler_counter + 1;
else
newClock <= not newClock;
prescaler_counter <= 0;
end if;
end if;
end process;
SCLK <= newClock;
-- FPGA transmit data on falling_edge
-- FPGA reads data on rising_edge
SPI_state: process(newClock)
begin
if rising_edge(newClock) then -- ADC læser på rising, derfor sendes på falling edge
case state is
when start =>
debug_tx <= "0001";
CS <= '1';
MOSI <= '0';
busy <= '1';
RX <= "0000000000";
state <= state2;
when state2 => -- Send init bits.
debug_tx <= "0010";
CS <= '0';
shift_counter <= shift_counter - 1;
TX <= TX(N-1 downto 0) & TX(N);
MOSI <= TX(N);
if shift_counter = 0 then
MOSI <= '0';
shift_counter<= 11;
state <= state3;
end if;
when state3 =>
debug_tx <= "0100";
--MOSI <= '0';
CS <= '0'; -- Last bit init bit;
state <= state5;
--when state4=>
-- debug_tx <= "1000";
-- CS <= '0'; --T_sample from falling - falling
-- state <= state5;
when state5=>
debug_tx <= "1001";
CS <= '0'; -- Read
shift_counter <= shift_counter - 1;
RX <= RX(8 downto 0) & MISO;
if shift_counter = 0 then
MOSI <= '0';
shift_counter<= N;
busy <= '0';
state <= start;
end if;
when others =>
debug_tx <= "1111";
state <= start;
end case;
end if;
end process;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adc_tb is
end adc_tb;
architecture arch of adc_tb is
-- Component declaration of the tested unit
component main
port(
clk : in std_logic;
sclk : out std_logic;
miso : in std_logic;
mosi : out std_logic;
cs : out std_logic;
debug_tx : out std_logic_vector(3 downto 0);
RX_LEd: out std_logic_vector(9 downto 0)
);
end component;
-- Stimulus signals - signals mapped to the input and inout ports of tested entity
signal sclk : std_logic := '0'; -- the sample clock
signal clk : std_logic := '0';
signal dout : std_logic := 'Z';
signal din : std_logic;
signal debug_tx: std_logic_vector (3 downto 0) := "0000";
signal RX_LEd: std_logic_vector(9 downto 0) := "0000000000";
-- Observed signals - signals mapped to the output ports of tested entity
signal cs : std_logic;
signal adc_data : std_logic_vector(9 downto 0);
-- clock period
constant period : time := 20 ns; -- 50 MHz clock
-- constant data set that will be sent back as the ADC data
constant FIXED_DATA : std_logic_vector(9 downto 0) := std_logic_vector(to_unsigned(1023,10));
-- timing parameters from the datasheet
constant T_HI : time := 125 ns; -- CLK high time
constant T_LO : time := 125 ns; -- CLK low time
constant T_SUCS : time := 100 ns; -- CS Fall to first rising CLK edge
constant T_DO : time := 125 ns; -- CLK fall to output data valid ( 125ns at 5V )
constant T_EN : time := 125 ns; -- CLK fall to output enable ( 125ns at 5V )
constant T_DIS : time := 100 ns; -- CS Rise to output disable
constant T_CSH : time := 270 ns; -- CS disable time
constant T_R : time := 100 ns; -- D_OUT rise time
constant T_F : time := 100 ns; -- D_OUT fall time
begin
---- Unit Under Test port map
UUT : main
port map (
clk => clk,
sclk => sclk,
miso => dout,
mosi => din,
cs => cs,
debug_tx => debug_tx,
RX_LEd => RX_LEd
);
-- generate the clock
clk <= not clk after period/2;
-- emulate what the MCP3001 ADC is doing, by sending back some test data
-- this process uses the timing diagram (Fig. 1) from 21293C.pdf
process
variable differential : boolean := false;
variable channel_sel : unsigned(2 downto 0) := "000";
begin
-- Set the data line to HI-Z
dout <= 'Z';
-- wait until the CS is brought to '0', this starts the conversion.
-- also check for an error where there is a rising edge that happens
-- less than 100 ns after CS is brought to '0'
wait until falling_edge(cs);
if sclk = '0' then
wait for T_SUCS;
assert sclk = '0'
report "Timing constraint Tsucs=100ns violated, clock rising edge must come atleast 100ns after CS transitions to '0'"
severity error;
else
wait for T_SUCS;
end if;
-- wait for the start bit
if din = '0' then
wait until rising_edge(din);
end if;
-- handle the input mode and channel select
-- setup and hold times are not checked
wait until falling_edge(sclk);
wait until rising_edge(sclk);
if din = '1' then
differential := false;
else
differential := true;
end if;
for i in 2 downto 0 loop
wait until rising_edge(sclk);
channel_sel(i) := din;
end loop;
if differential then
report "sampling in differential mode on channel " & integer'image(to_integer(channel_sel));
else
report "sampling in differential mode on channel " & integer'image(to_integer(channel_sel));
end if;
-- sample time...
wait until falling_edge(sclk);
wait until falling_edge(sclk);
wait for T_EN; -- small delay time after falling edge from datasheet
dout <= '0';
-- output the converted data MSB first after every falling edge.
-- also check for a likely problem where the CS is not held at '0' while
-- reading all 10 bits of data.
for i in 9 downto 0 loop
wait until falling_edge(sclk);
wait for T_DO; -- small delay time after falling edge from datasheet
dout <= FIXED_DATA(i);
assert cs = '0'
report "CS needs to be held at '0', not all bits have been transmitted"
severity warning;
end loop;
-- wait for CS to go back high then disable the output
wait until rising_edge(cs);
wait for T_DIS;
dout <= 'Z';
-- wait for the minimum delay time before the start of the next sample.
-- also check for a likely error, where CS is only '1' for a single
-- 320ns clock period
wait for T_CSH-T_DIS;
assert cs = '1'
report "Timing Constraint Tcsh=350ns violated, CS needs to be held to '1' for atleast 350ns before transitioning to '0'"
severity error;
end process;
end arch;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_logic_unsigned.all; use ieee.numeric_std.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity main is Port ( MISO : in STD_LOGIC; MOSI : out STD_LOGIC; CS : out STD_LOGIC; SCLK : out STD_LOGIC; CLK : in STD_LOGIC; debug_TX: out std_logic_vector(3 downto 0); tx_pwm: out std_logic_vector(1 downto 0); work: out std_logic; rx_led: out std_logic_vector(9 downto 0) ); end main; architecture Behavioral of main is --signal prescaler : integer range 0 to 3500000 := 3500000 ; constant N : integer := 4; signal prescaler_counter : integer range 0 to 50000000 := 0; signal newClock : std_logic := '0'; signal TX :std_logic_vector(N downto 0) := "11000"; signal RX : std_logic_vector(9 downto 0) := "0000000000"; type state_type is (start,state2,state3,state5); --type of state machine. type TXRX is (waiting, working); signal state : state_type := start; signal busy: std_logic:= '0'; signal shift_counter: integer range 0 to 750:= N; begin prescaler01: process(clk, newClock) begin if rising_edge(clk) then if prescaler_counter < 5000000 then -- 14 prescaler_counter <= prescaler_counter + 1; else newClock <= not newClock; prescaler_counter <= 0; end if; end if; end process; SCLK <= newClock; -- FPGA transmit data on falling_edge -- FPGA reads data on rising_edge SPI_state: process(newClock) begin if rising_edge(newClock) then -- ADC læser på rising, derfor sendes på falling edge case state is when start => debug_tx <= "0001"; CS <= '1'; MOSI <= '0'; busy <= '1'; RX <= "0000000000"; state <= state2; when state2 => -- Send init bits. debug_tx <= "0010"; CS <= '0'; shift_counter <= shift_counter - 1; TX <= TX(N-1 downto 0) & TX(N); MOSI <= TX(N); if shift_counter = 0 then MOSI <= '0'; shift_counter<= 11; state <= state3; end if; when state3 => debug_tx <= "0100"; --MOSI <= '0'; CS <= '0'; -- Last bit init bit; state <= state5; --when state4=> -- debug_tx <= "1000"; -- CS <= '0'; --T_sample from falling - falling -- state <= state5; when state5=> debug_tx <= "1001"; CS <= '0'; -- Read shift_counter <= shift_counter - 1; RX <= RX(8 downto 0) & MISO; if shift_counter = 0 then MOSI <= '0'; shift_counter<= N; busy <= '0'; state <= start; end if; when others => debug_tx <= "1111"; state <= start; end case; end if; end process;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity adc_tb is end adc_tb; architecture arch of adc_tb is -- Component declaration of the tested unit component main port( clk : in std_logic; sclk : out std_logic; miso : in std_logic; mosi : out std_logic; cs : out std_logic; debug_tx : out std_logic_vector(3 downto 0); RX_LEd: out std_logic_vector(9 downto 0) ); end component; -- Stimulus signals - signals mapped to the input and inout ports of tested entity signal sclk : std_logic := '0'; -- the sample clock signal clk : std_logic := '0'; signal dout : std_logic := 'Z'; signal din : std_logic; signal debug_tx: std_logic_vector (3 downto 0) := "0000"; signal RX_LEd: std_logic_vector(9 downto 0) := "0000000000"; -- Observed signals - signals mapped to the output ports of tested entity signal cs : std_logic; signal adc_data : std_logic_vector(9 downto 0); -- clock period constant period : time := 20 ns; -- 50 MHz clock -- constant data set that will be sent back as the ADC data constant FIXED_DATA : std_logic_vector(9 downto 0) := std_logic_vector(to_unsigned(1023,10)); -- timing parameters from the datasheet constant T_HI : time := 125 ns; -- CLK high time constant T_LO : time := 125 ns; -- CLK low time constant T_SUCS : time := 100 ns; -- CS Fall to first rising CLK edge constant T_DO : time := 125 ns; -- CLK fall to output data valid ( 125ns at 5V ) constant T_EN : time := 125 ns; -- CLK fall to output enable ( 125ns at 5V ) constant T_DIS : time := 100 ns; -- CS Rise to output disable constant T_CSH : time := 270 ns; -- CS disable time constant T_R : time := 100 ns; -- D_OUT rise time constant T_F : time := 100 ns; -- D_OUT fall time begin ---- Unit Under Test port map UUT : main port map ( clk => clk, sclk => sclk, miso => dout, mosi => din, cs => cs, debug_tx => debug_tx, RX_LEd => RX_LEd ); -- generate the clock clk <= not clk after period/2; -- emulate what the MCP3001 ADC is doing, by sending back some test data -- this process uses the timing diagram (Fig. 1) from 21293C.pdf process variable differential : boolean := false; variable channel_sel : unsigned(2 downto 0) := "000"; begin -- Set the data line to HI-Z dout <= 'Z'; -- wait until the CS is brought to '0', this starts the conversion. -- also check for an error where there is a rising edge that happens -- less than 100 ns after CS is brought to '0' wait until falling_edge(cs); if sclk = '0' then wait for T_SUCS; assert sclk = '0' report "Timing constraint Tsucs=100ns violated, clock rising edge must come atleast 100ns after CS transitions to '0'" severity error; else wait for T_SUCS; end if; -- wait for the start bit if din = '0' then wait until rising_edge(din); end if; -- handle the input mode and channel select -- setup and hold times are not checked wait until falling_edge(sclk); wait until rising_edge(sclk); if din = '1' then differential := false; else differential := true; end if; for i in 2 downto 0 loop wait until rising_edge(sclk); channel_sel(i) := din; end loop; if differential then report "sampling in differential mode on channel " & integer'image(to_integer(channel_sel)); else report "sampling in differential mode on channel " & integer'image(to_integer(channel_sel)); end if; -- sample time... wait until falling_edge(sclk); wait until falling_edge(sclk); wait for T_EN; -- small delay time after falling edge from datasheet dout <= '0'; -- output the converted data MSB first after every falling edge. -- also check for a likely problem where the CS is not held at '0' while -- reading all 10 bits of data. for i in 9 downto 0 loop wait until falling_edge(sclk); wait for T_DO; -- small delay time after falling edge from datasheet dout <= FIXED_DATA(i); assert cs = '0' report "CS needs to be held at '0', not all bits have been transmitted" severity warning; end loop; -- wait for CS to go back high then disable the output wait until rising_edge(cs); wait for T_DIS; dout <= 'Z'; -- wait for the minimum delay time before the start of the next sample. -- also check for a likely error, where CS is only '1' for a single -- 320ns clock period wait for T_CSH-T_DIS; assert cs = '1' report "Timing Constraint Tcsh=350ns violated, CS needs to be held to '1' for atleast 350ns before transitioning to '0'" severity error; end process; end arch;
The problem is when Vdd = Vref = CH0 = 3.3V i don't get an binary value of 1111111111 , but rather something like 1111110111, or something like that , point being never a stream of only ones.
when state2 => -- Send init bits.
debug_tx <= "0010";
CS <= '0';
[COLOR="#FF0000"]shift_counter <= shift_counter - 1; -- Dies here[/COLOR]
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?