Forum Discussion
Filter & decimation implementation on AD7401
Hello everybody!
We have chosen the AD7401 Sigma Delta modulator for our project, translated the Verilog code given by the datasheet into VHDL and are now confused about the results of the simulation. We have attached our translated VHDL code plus the datasheet of AD7401. 1) We will give the master clock from the FPGA to the ADC from one of the I/O pins. The clocks don't seem to be synchronized though, there is a 5nsec latch delay. Should that be ok, or do we have to eliminate that delay somehow? 2) We tried to simulate the data flow inputting only ones '1', but result is really not the expected one. (DATA samples should be at the highest level?!) Yes, but what about overflow? The given interface is permitting that, if such a case comes up. Below are some results of a random inputted bit stream and a only '1' bit stream. http://i252.photobucket.com/albums/hh3/unoturbomk2/samples.jpg http://i252.photobucket.com/albums/hh3/unoturbomk2/samples2.jpg *** Is the code correct? *** We'd appreciate any kind of help! Thanks in advance!27 Replies
- Altera_Forum
Honored Contributor
k,
any news regarding your issue? Have you been able to solve it? I took another quick look on the files you'd attached, and I might have found out what could be causing your issue. How are you CLOCKING your design? What frequency are you providing AD7401 with, and what frequency do you clock your design with? If you're using different clock domains, you might want to try clocking the whole design with the same frequency. Let us know how you're doing! - Altera_Forum
Honored Contributor
Sorry, you are right - I totally misunderstood you...
Correct, when applying a constant voltage within the recommended or max input values of AD7401, the filter's response should be a stable output representing the applied voltage as described in its datasheet. We had checked such issues in simulation and they had all been solved; in real world we went straight to the actual implementation, which, as already mentioned, worked perfectly. Let's check step by step: You are saying that it is "fluctuating" within a rather broad range, meaning that: 1) it does NOT overflow, correct? 2) it DOES produce an output - does aforementioned range at least include the value that should be the output according to your constant input voltage? 3) have you checked what input you really apply? I mean, maybe your source is unstable, etc. The filter code is correct - it has been simulated and used in a real implementation; as I told you in my previous post (even though having misunderstood you :P), I think it is best for you if you try to look for the error elsewhere first. BR, David - Altera_Forum
Honored Contributor
You must misunderstand what I meant.I measured the voltage is uncertain, of course, I want to say is that when I measured the voltage to a constant value, the AD7401 measurement result should be a value fluctuating within a narrow range.My situation now is that it measured the AD value is very unstable, the fluctuation range is too large.
I will take your advice, thank you. I need to finish the work with two AD7401 which were measuring the 800V series battery voltage(Precision resistor divider less than 200 mv to put in the AD7401) and shunt (Specification 600A-75mv) current sampling voltage. - Altera_Forum
Honored Contributor
Wait a sec, what exactly are you trying to do? Why would you want to measure a constant voltage with such an expensive Σ-Δ modulator? Anyway, we had applied an audio signal (the output of a simple ECM, filtered and amplified) as an input to AD7401 and it worked perfectly.
I suggest you take a closer look at AD7401's datasheet and its Specs, as I suspect that you have overlooked specific details that might be vital for the correct operation of this component. - Altera_Forum
Honored Contributor
I use it but it doesn't work correctly.Because the DATA[15..0] I get was not stable and fluctuates about 1000,which it's terrible for the measure of a fixed voltage.I wrote a simple I2C (not the standard) to get the DATA[15..0] from the FPGA and send to DSP.
What did you do with the DATA[15..0]?Is it stable for a fixed sampling voltage?And how is the linearity of the AD7401 used of the filter code you wrote? I'm really sorry to bother you to answer this question, but I do encounter difficulties. - Altera_Forum
Honored Contributor
1、I don't know why it can't work.Is it right to create symbols of VHDL and verilog program and then put them together in a block diagram to compile?(Set the block diagram as the top-level entity)
The program of vhdl I used can't work in the block diagram.I set the word_clk as output pin and observe it by scope and can't get any square wave. => The problem above has been solved. But it works not correctly.Because the DATA[15..0] I get was not stable and fluctuates about 1000,which it's terrible for the measure of a fixed voltage. 2、The word_clk signal is get by dividing the signal of mclk. decimation rate=Divider ratio=f(mclk)/f(word_clk) The frequency is got as follows: sysclk (50MHZ Crystal ) -> MCLK(6.25MHZ drive the AD7401 ) ->word_clk (decimation rate=256,24.41KHZ to enable the Differentiators) - Altera_Forum
Honored Contributor
--- Quote Start --- I used the code you write to debug to the actual circuit not simulation, and found it cannot produce WORD_CLK clock signal, so I have written in verilog a divider circuit, to produce mclk and word_clk signal. --- Quote End --- And why don't you get a valid word_clk signal? Apparently it worked in the original design. Whatever the problem is, there have been good reasons to use word_clk as a clock enable instead of a divided (or so called "ripple") clock for the slow CIC frequency. A ripple clock brings up timing violation for the domain crossing signals, it's just a bad design method. - Altera_Forum
Honored Contributor
Thank you first. @dfuschelberger
- Altera_Forum
Honored Contributor
Hi,
sorry but currently I have no time to look into your issue. I have attached our filter block, which had worked for us (in a real implementation). It contains the part of code that you need. Please disregard the last section tagged as "RAM Writing Process" and its associated signals, and adjust "DATA Assignment Process" to your needs. Hope it helps! BR, David - Altera_Forum
Honored Contributor
Sir, Hello!
I used the code you write to debug to the actual circuit not simulation, and found it cannot produce word_clk clock signal, so I have written in verilog a divider circuit, to produce mclk and word_clk signal, and made ​​some changes to your program (Delete word_clk produce circuit ), and then debug, I find the result of the conversion are all 0 (DATA [15 .. 0]).After all, it cannot work in actual circuit.I don't know why,Could you tell me?Have you ever used the AD7401 to apply a actual project such as a sampling circuit of voltage? The following is a modified program of you: library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity AD7401decimationfilter is port(reset, mdata, clk20,word_clk: in std_logic; DATA : out std_logic_vector(15 downto 0); ads_clk : out std_logic); end AD7401decimationfilter; architecture RTL of AD7401decimationfilter is signal CN2_D2,DN1_D,DN2_D,DN1,DN2,DN3 : std_logic_vector(24 downto 0); signal CN1, CN2 : std_logic_vector(24 downto 0); signal delta : std_logic_vector(24 downto 0); --signal word_count : std_logic_vector(7 downto 0); --signal word_clk : std_logic; begin ads_clk <= clk20; p11:process(clk20, reset) begin if reset = '0' then delta <= (others => '0'); elsif clk20'event and clk20 = '1' then -- if mdata = '1' then delta <= delta + 1;--mdata; --end if; end if; end process p11; p12:process(reset, clk20) begin if reset = '0' then CN1 <= (others => '0'); CN2 <= (others => '0'); elsif clk20'event and clk20 = '1' then CN1 <= CN1 + delta ; CN2 <= CN2 + CN1; end if; end process p12; --DECIMATION STAGE (MCLKIN/WORD_CLK) --process(clk20,reset) --begin -- if reset ='0' then -- word_count <= "00000000";--(others => '0'); -- elsif clk20'event and clk20 = '0' then -- if word_count="11111111" then -- word_count<="00000001"; -- else word_count <= word_count + 1; -- word_count is an 8 bit reg for decimation 2^8= 256 -- end if; -- end if; --end process; --process(word_count,reset) --begin --if reset = '0' then -- word_clk <= '0'; -- oe<='0'; --else -- word_clk <= word_count(7); -- oe<=word_count(7); --end if; --end process; p13:process(reset, word_clk) begin if reset = '0' then CN2_D2 <= (others => '0'); DN1_D <= (others => '0'); DN2_D <= (others => '0'); DN1 <= (others => '0'); DN2 <= (others => '0'); DN3 <= (others => '0'); elsif word_clk'event and word_clk = '1' then DN1 <= CN2 - CN2_D2; DN2 <= DN1 - DN1_D; DN3 <= DN2 - DN2_D; CN2_D2 <= CN2; DN1_D <= DN1; DN2_D <= DN2; end if; end process p13; --p14:process(word_clk,reset) --begin -- if reset = '0' then -- DATA <= (others => '0'); -- elsif word_clk'event and word_clk = '1' then -- DATA(15 downto 0) <= DN3(23 downto 8); -- extracting the Most Significant Bits MSB -- end if; --end process p14; process(clk20,reset) begin if reset = '0' then DATA <= (others => '0'); elsif clk20'event and clk20 = '1' then if word_clk = '1' then if DN3(24) = '1' then DATA(15 downto 0) <= (others => '1'); else DATA(15 downto 0) <= DN3(23 downto 8); end if; end if; end if; end process; end RTL; *i wrote it myself sub-frequency signal procedure as follows: module dividefrequency(sysclk,reset,mclk1,mclk2,word_clk); input sysclk; input reset; output mclk1; output mclk2; output word_clk; wire sysclk; wire reset; reg mclk1; wire mclk2; reg word_clk; reg [31:0] div_count; reg [7:0] word_count; integer location; integer info_file; //wire [7:0] dec_rate; //parameter rate=256;//280wen,256(12M);//70->1/2 i2c//116->1.4*16; //parameter h_rate=64; //assign dec_rate = 256 - rate;//ini value assign mclk2=mclk1; /* initial begin end */ /*divide sysclk 50MHZ to 6.25MHZ*/ always @(posedge reset or negedge sysclk) if(reset) begin div_count<=0; end else begin div_count<=div_count+1; if(div_count==8) div_count<=1'b1; end always @(div_count,mclk1)//mclk begin if(div_count<=4) mclk1<=1; else if(div_count<=8) mclk1<=0; end always @ (negedge mclk1 or posedge reset) begin if (reset) word_count <= 0; else if (word_count == 8'hFF) word_count <=1;// dec_rate+1; else word_count <= word_count + 1; end /* always @ (word_count) word_clk <= word_count[8]; */ always @ (word_count) begin if(word_count<=64)//64) word_clk<=1; else if(word_count<=8'hff)//255) word_clk<=0; end endmodule sysclk is 50mhz,which is divided to 6.25mhz as mclk and 24.41khz as word_clk.