- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
11-26-2009 08:51 AM
Hallo,
I try to play a little bit with ad and da converters on my Spartan 3e board. I found some projects which use picoblaze to ensure communication between adc dac and fpga. Now I would like to implement it without using picoblaze (just for practice). I wrote a programm but it does not work in propper way. Below I pasted my code and screen from oscilloscope with input signal (sin wave to channel A adc) and output (from channel A dac). I gues that problem is in differences of bit representations in adc (14-bit twos complement signed) and dac (unsigned digital value).I would be very grateful for a help.
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
--------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
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 control is
Port ( rst : in STD_LOGIC;
clk : in STD_LOGIC;
-- switch0 : in STD_LOGIC;
rot_a : in STD_LOGIC;
rot_b : in STD_LOGIC;
sdo : in STD_LOGIC;
sdi : out STD_LOGIC;
sck : out STD_LOGIC;
amp_cs : out STD_LOGIC;
amp_shdn : out STD_LOGIC;
ad_conv : out std_logic;
da_cs : out std_logic;
da_clr : out std_logic;
strataflash_we : out STD_LOGIC;
strataflash_oe : out STD_LOGIC;
strataflash_ce : out STD_LOGIC;
platformflash_oe : out std_logic;
simple_io : out STD_LOGIC_VECTOR (3 downto 0);
led : out STD_LOGIC_VECTOR (7 downto 0));
end control;
architecture Behavioral of control is
signal state_reg, state_next : std_logic_vector (1 downto 0) := "00";
constant amp_state : std_logic_vector (1 downto 0) := "00";
constant ad_state : std_logic_vector (1 downto 0) := "01";
constant fir_state : std_logic_vector (1 downto 0) := "10";
constant da_state : std_logic_vector (1 downto 0) := "11";
signal sck_reg, sck_next, sdi_reg, sdi_next : std_logic := '0';
--rotary filter
signal rotary_in : std_logic_vector (1 downto 0) := "00";
signal rotary_q1 : std_logic := '0';
signal rotary_q2 : std_logic := '0';
signal delay_rotary_q1 : std_logic := '0';
signal rotary_event : std_logic := '0';
signal rotary_left : std_logic := '0';
signal led_pattern_reg, led_pattern_next : std_logic_vector (7 downto 0) := "00010001";
--amp
signal amp_state_reg, amp_state_next : std_logic_vector (2 downto 0) := "000";
constant amp_idle : std_logic_vector (2 downto 0) := "000";
constant amp_wait1 : std_logic_vector (2 downto 0) := "001";
constant amp_sck1 : std_logic_vector (2 downto 0) := "010";
constant amp_wait2 : std_logic_vector (2 downto 0) := "011";
constant amp_end : std_logic_vector (2 downto 0) := "100";
signal amp_data_reg, amp_data_next : std_logic_vector (7 downto 0) := "00010001";
signal amp_cs_reg, amp_cs_next : std_logic := '1';
signal amp_bit_reg, amp_bit_next : natural range 0 to 8 := 8;
--ad
signal ad_state_reg, ad_state_next : std_logic_vector (3 downto 0) := "0000";
constant ad_idle : std_logic_vector (3 downto 0) := "0000";
constant ad_conv0 : std_logic_vector (3 downto 0) := "0001";
constant ad_sck1 : std_logic_vector (3 downto 0) := "0010";
constant ad_sck0 : std_logic_vector (3 downto 0) := "0011";
constant ad_cnt_update : std_logic_vector (3 downto 0) := "0100";
constant ad_loop : std_logic_vector (3 downto 0) := "0101";
constant ad_data_adjust1 : std_logic_vector (3 downto 0) := "0110";
constant ad_data_adjust2 : std_logic_vector (3 downto 0) := "0111";
constant ad_end : std_logic_vector (3 downto 0) := "1000";
signal ad_conv_reg, ad_conv_next : std_logic := '0';
signal ad_bit_reg, ad_bit_next : natural range 0 to 34 := 34;
signal ad_data_reg, ad_data_next : std_logic_vector (33 downto 0) := (others => '0');
signal ad_channel1_reg, ad_channel1_next : std_logic_vector (13 downto 0) := (others => '0');
--da
signal da_state_reg, da_state_next : std_logic_vector (2 downto 0) := (others => '0');
constant da_idle : std_logic_vector (2 downto 0) := "000";
constant da_send : std_logic_vector (2 downto 0) := "001";
constant da_sck1 : std_logic_vector (2 downto 0) := "010";
constant da_loop : std_logic_vector (2 downto 0) := "011";
constant da_end : std_logic_vector (2 downto 0) := "100";
constant vref : unsigned (13 downto 0) := "00001000000000";
signal da_cs_reg, da_cs_next : std_logic := '1';
signal da_bit_reg, da_bit_next : natural range 0 to 32 := 32;
signal da_data_reg, da_data_next : std_logic_vector (31 downto 0) := (others => '0');
--fir
signal fir_state_reg, fir_state_next : std_logic_vector (1 downto 0) := "00";
constant fir0 : std_logic_vector (1 downto 0) := "00";
constant fir1 : std_logic_vector (1 downto 0) := "01";
begin
process(clk, rst)
begin
if rst = '1' then
state_reg <= amp_state;
elsif clk'event and clk = '1' then
state_reg <= state_next;
end if;
end process;
rotary_filter: process(clk)
begin
if clk'event and clk = '1' then
rotary_in <= ROT_B & ROT_A;
case rotary_in is
when "00" => rotary_q1 <= '0';
rotary_q2 <= rotary_q2;
when "01" => rotary_q1 <= rotary_q1;
rotary_q2 <= '0';
when "10" => rotary_q1 <= rotary_q1;
rotary_q2 <= '1';
when "11" => rotary_q1 <= '1';
rotary_q2 <= rotary_q2;
when others => rotary_q1 <= rotary_q1;
rotary_q2 <= rotary_q2;
end case;
end if;
end process rotary_filter;
direction: process(clk)
begin
if clk'event and clk = '1' then
delay_rotary_q1 <= rotary_q1;
if rotary_q1 = '1' and delay_rotary_q1 = '0' then
rotary_event <= '1';
rotary_left <= rotary_q2;
else
rotary_event <= '0';
rotary_left <= rotary_left;
end if;
end if;
end process direction;
process(rst, clk)
begin
if rst = '1' then
led_pattern_reg <= "00010001";
elsif clk'event and clk = '1' then
led_pattern_reg <= led_pattern_next;
end if;
end process;
led_pattern_next <= (led_pattern_reg(7 downto 4) + 1) & (led_pattern_reg(3 downto 0) + 1) when (led_pattern_reg < "01110111" and rotary_event = '1' and rotary_left = '1') else
(led_pattern_reg(7 downto 4) - 1) & (led_pattern_reg(3 downto 0) - 1) when (led_pattern_reg > "00010001" and rotary_event = '1' and rotary_left = '0') else
led_pattern_reg;
led <= led_pattern_reg;
--main case
process(clk, rst)
begin
if rst = '1' then
sck_reg <= '0';
sdi_reg <= '0';
elsif clk'event and clk = '1' then
sck_reg <= sck_next;
sdi_reg <= sdi_next;
end if;
end process;
--amp ff
process(clk, rst)
begin
if rst = '1' then
amp_state_reg <= amp_idle;
amp_data_reg <= (others => '0');
amp_cs_reg <= '1';
amp_bit_reg <= 8;
elsif clk'event and clk = '1' then
amp_state_reg <= amp_state_next;
amp_data_reg <= amp_data_next;
amp_cs_reg <= amp_cs_next;
amp_bit_reg <= amp_bit_next;
end if;
end process;
--ad ff
process(clk, rst)
begin
if rst = '1' then
ad_state_reg <= ad_idle;
ad_conv_reg <= '0';
ad_bit_reg <= 34;
ad_data_reg <= (others => '0');
ad_channel1_reg <= (others => '0');
elsif clk'event and clk = '1' then
ad_state_reg <= ad_state_next;
ad_conv_reg <= ad_conv_next;
ad_bit_reg <= ad_bit_next;
ad_data_reg <= ad_data_next;
ad_channel1_reg <= ad_channel1_next;
end if;
end process;
--da ff
process(clk, rst)
begin
if rst = '1' then
da_state_reg <= da_idle;
da_cs_reg <= '1';
da_bit_reg <= 32;
da_data_reg <= (others => '0');
fir_state_reg <= fir0;
elsif clk ' event and clk = '1' then
da_state_reg <= da_state_next;
da_cs_reg <= da_cs_next;
da_bit_reg <= da_bit_next;
da_data_reg <= da_data_next;
fir_state_reg <= fir_state_next;
end if;
end process;
process(rotary_event, state_reg, led_pattern_reg, amp_state_reg, amp_bit_reg, ad_state_reg, ad_bit_reg, sdo, ad_data_reg, da_state_reg, da_bit_reg, da_data_reg, fir_state_reg)
begin
--amp
state_next <= state_reg;
amp_data_next <= amp_data_reg;
amp_state_next <= amp_state_reg;
amp_cs_next <= amp_cs_reg;
sdi_next <= sdi_reg;
sck_next <= sck_reg;
amp_bit_next <= amp_bit_reg;
--ad
ad_state_next <= ad_state_reg;
ad_channel1_next <= ad_channel1_reg;
ad_bit_next <= ad_bit_reg;
ad_conv_next <= ad_conv_reg;
--da
da_state_next <= da_state_reg;
da_cs_next <= da_cs_reg;
da_bit_next <= da_bit_reg;
da_data_next <= da_data_reg;
--fir
fir_state_next <= fir_state_reg;
case state_reg is
when amp_state =>
case amp_state_reg is
when amp_idle =>
amp_bit_next <= 8;
amp_data_next <= led_pattern_reg;
amp_cs_next <= '0';
sck_next <= '0';
amp_state_next <= amp_wait1;
when amp_wait1 =>
sdi_next <= amp_data_reg(amp_bit_reg - 1);
amp_state_next <= amp_sck1;
when amp_sck1 =>
sck_next <= '1';
amp_bit_next <= amp_bit_reg - 1;
amp_state_next <= amp_wait2;
when amp_wait2 =>
if amp_bit_reg > 0 then
amp_state_next <= amp_wait1;
else
amp_state_next <= amp_end;
end if;
sck_next <= '0';
when amp_end =>
sck_next <= '0';
sdi_next <= '0';
amp_cs_next <= '1';
amp_state_next <= amp_idle;
state_next <= ad_state;
when others => amp_state_next <= amp_idle;
end case;
when ad_state =>
case ad_state_reg is
when ad_idle =>
ad_data_next <= (others => '0');
ad_conv_next <= '1';
ad_bit_next <= 34;
sck_next <= '0';
ad_state_next <= ad_conv0;
when ad_conv0 =>
ad_conv_next <= '0';
ad_state_next <= ad_sck1;
when ad_sck1 =>
sck_next <= '1';
ad_state_next <= ad_sck0;
when ad_sck0 =>
sck_next <= '0';
ad_data_next(ad_bit_reg - 1) <= sdo;
ad_state_next <= ad_cnt_update;
when ad_cnt_update =>
ad_bit_next <= ad_bit_reg - 1;
ad_state_next <= ad_loop;
when ad_loop =>
if ad_bit_reg > 0 then
ad_state_next <= ad_sck1;
else
ad_state_next <= ad_data_adjust1;
--ad_data_next(33 downto 26) <= ad_data_reg(33 downto 26);
end if;
when ad_data_adjust1 =>
ad_data_next <= ad_data_reg(33) & ad_data_reg(33) & ad_data_reg(33 downto 2);
ad_state_next <= ad_data_adjust2;
when ad_data_adjust2 =>
ad_data_next <= ad_data_reg + x"0400";
ad_state_next <= ad_end;
when ad_end =>
ad_channel1_next <= ad_data_reg(33 downto 20);
-- ad_channel2_next <= ad_data_reg(15 downto 2);
ad_state_next <= ad_idle;
state_next <= fir_state;
sck_next <= '0';
when others => ad_state_next <= ad_idle;
end case;
when fir_state =>
case fir_state_reg is
when fir0 =>
fir_state_next <= fir1;
when fir1 =>
state_next <= da_state;
fir_state_next <= fir0;
when others => fir_state_next <= fir0;
end case;
when da_state =>
case da_state_reg is
when da_idle =>
da_cs_next <= '0';
sck_next <= '0';
da_bit_next <= 32;
da_data_next <= "0000000000110000" & ad_channel1_reg(13 downto 2) & "0000";
da_state_next <= da_send;
when da_send =>
sdi_next <= da_data_reg(da_bit_reg - 1);
da_state_next <= da_sck1;
when da_sck1 =>
sck_next <= '1';
da_bit_next <= da_bit_reg - 1;
da_state_next <= da_loop;
when da_loop =>
if da_bit_reg > 0 then
da_state_next <= da_send;
else
da_state_next <= da_end;
end if;
sck_next <= '0';
when da_end =>
da_cs_next <= '1';
sck_next <= '0';
da_state_next <= da_idle;
state_next <= amp_state;
when others => da_state_next <= da_idle;
end case;
when others => state_next <= amp_state;
end case;
end process;
simple_io(0) <= sck_reg;
simple_io(1) <= sdo;
simple_io(2) <= sdi_reg;
simple_io(3) <= da_cs_reg;
sdi <= sdi_reg;
sck <= sck_reg;
amp_shdn <= rst;
amp_cs <= amp_cs_reg;
ad_conv <= ad_conv_reg;
da_cs <= da_cs_reg;
da_clr <= not rst;
strataflash_oe <= '1';
strataflash_ce <= '1';
strataflash_we <= '1';
platformflash_oe <= '0';
end Behavioral;
Solved! Go to Solution.
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
11-26-2009 09:42 AM
Hi
looks to me as if your code in actuality is working,
have you tried simulating.
One comment first
it's 'nice' to attach the code as a zip file, much easier to read the post, and to look at the code.
Anyway.
AS you suggest, it looks as if you have the ADC / DAC working with different codes.
You have the ADC outputting 2's compliment, and the DAC accepting straight binary.
To convert from one to the other you need:
http://en.wikipedia.org/wiki/Two%27s_complement
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
11-29-2009 11:46 PM
Hi,
Thank you for a reply, I have found an error. The problem was not with 2's complement to binary conversion but with scaling of data form ad converter.
Best regards
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
12-08-2009 07:39 AM
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
03-24-2011 09:02 AM
Is it possible to declare what the signals stand for?
I'm trying to make my own code, and was trying to understand and use this code, but when I compare your names listed (e.g. sdo, sdi) with the user guide of the spartan board, I don't know which are equal (e.g. sdo = (perhaps) spi_miso).
Greetings
Re: adc dca Spartan3e
[ Edited ]- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
03-29-2011 01:42 AM - edited 03-29-2011 02:50 AM
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
03-29-2011 09:32 AM
wouterdevriese wrote:
Is it possible to declare what the signals stand for?
I'm trying to make my own code, and was trying to understand and use this code, but when I compare your names listed (e.g. sdo, sdi) with the user guide of the spartan board, I don't know which are equal (e.g. sdo = (perhaps) spi_miso).
Greetings
I always give my FPGA signals names that are meaningful, and I always make the schematic netnames match the FPGA pin signal names. Most of my designs have more than one SPI interface, so I like to assign a prefix to each group, like:
adcSpiSCLK
adcSpiMISO
adcSpiCS_l (_l for active low)
dacSpiSCLK
dacSpiMOSI
dacSpiCS_l
etc.
----------------------------------------------------------------
Yes, I do this for a living.
Re: adc dca Spartan3e
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
03-29-2011 09:54 AM
don 't know if this helps or confuses
in SPI / motorola world,
they have a master and a number of slaves.
master drives the chip select signals, and the serial bit clock
MISO, is Master in Slave out , serial data out of the Slave to the master
MOSI, is master Out , slave in, serial data out of the master , into the slave











