Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] How to connect my adc code to XILINX AXI4 FIR IP

Status
Not open for further replies.

tsillen

Junior Member level 1
Joined
Mar 30, 2017
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
283
Hello,

I have made my clk div code, adc code and DAC code and generated the FIR filter using XILINX's FIR COMPILER 6.3 for my spartan 6 FPGA.

My filter is running on 25MHz , adc and dac on 48kHz.

Now I have the following questions regarding connecting it to the AXI-4 FIR IP block;

1. Since my filter is running on 25MHz and the rest on 48kHz , I assume I need a FIFO (between ADC and FIR , FIR and DAC) in order to convert between the different clocks correct?
2. Since the ADC gets a whole sample in 1 rising edge adc clk (48 kHz) wouldn't the tready and tvalid AXI4 signals for that always be high (or should I put them low on the falling edge?)

I have done a good amount of research online but can't find much information regarding this.
I'd guess these are simple questions but hard to find answers for.

Any help and or tips are appreciated.

Any help or tips are appreciated Screenshot_1.png.
 

AXI-4 doesn't have signals named tready and tvalid it has signals named awready, awvalid, wready, wvalid, bready, bvalid, arready, arvalid, rready, rvalid.

Seems to me what you haven't done an online research for is the AXI-4 spec.

Xilinx's calls this AXi4 interface and it does have tvalid, tready signals
Screenshot_2.png
 

2. Since the ADC gets a whole sample in 1 rising edge adc clk (48 kHz) wouldn't the tready and tvalid AXI4 signals for that always be high (or should I put them low on the falling edge?)

I have done a good amount of research online but can't find much information regarding this.
I'd guess these are simple questions but hard to find answers for.
AXI-4 doesn't have signals named tready and tvalid it has signals named awready, awvalid, wready, wvalid, bready, bvalid, arready, arvalid, rready, rvalid.

Seems to me what you haven't done an online research for is the AXI-4 spec. None of the signals in AXI-4 transition off the falling edge of the AXI clock ACLK.

Download the spec it's from ARM's website after registration as a customer.

Section A3.2.1 Handshake process specifies how ready and valid are used.
The source generates the VALID signal to indicate when the
address, data or control information is available. The destination generates the READY signal to indicate that it can
accept the information. Transfer occurs only when both the VALID and READY signals are HIGH.
On master and slave interfaces there must be no combinatorial paths between input and output signals.
A source is not permitted to wait until READY is asserted before asserting VALID.
Once VALID is asserted it must remain asserted until the handshake occurs, at a rising clock edge at which VALID
and READY are both asserted.
A destination is permitted to wait for VALID to be asserted before asserting the corresponding READY.
If READY is asserted, it is permitted to deassert READY before VALID is asserted.

- - - Updated - - -

Ah, you didn't specify AXI-4 Streaming interface.

But the behavior of the ready/valid handshake is the same regardless. To transfer TVALID and TREADY must both be asserted. Neither signal should wait to assert before the other. If master needs to send assert TVALID and then wait for TREADY. If the slave can accept data assert TREADY and deassert on TVALID or leave TREADY asserted if the slave can always accept data.
 
Hi,

My filter is running on 25MHz , adc and dac on 48kHz.
If possible.. I strongly recommend to run both circuits with the same clock.

Klaus
 
Thank you for that information, I have registered and downloaded the full specification.
If I understand correctly it should be like this:

Screenshot_4.png

my spartan6 only has 16 DSP slices, my filter is 51 coefficients and since the filter only seems to be able to do everything in parallel it has to run on a higher frequency.

- - - Updated - - -

Changed code a bit, simulation results are attached;
Pasted File at April 5, 2017 2-48 AM.png
Screenshot_5.png

The problem I'm experiencing now is the filer clock difference (25MHz) and the adc clk difference (48KHz) correct ?
If so the xilinxs IP FIFO with CLK conversion seems to be the easiest way to solve this ?
 

Don't take screen captures of code. Put them in the text with syntax tags around the code.

e.g.
{syntax=vhdl}
your code
{/syntax}
Curly braces substituted for [ ] as I couldn't get the thing to not cut of the last closing syntax tag. grrrr.

Your code for both cases is incorrect. Do not use edge events in synthesizable code only the clock should be using rising_edge(clk_inadc) (preferred over the clk_inadc'event and clk_inadc = '1' code). Also don't use use wait until statements in synthesizable code.

Per the AXI specification all the signals between the master and slave are synchronous signals. Therefore you are waiting for the following condition to occur on a clock edge not on the edges of the tready or tvalid signals.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
process (clk_inadc)
begin
  if rising_edge(clk_inadc) then
    if (tready = '1' and tvalid = '1') then
      -- do this because data has been transferred.
    else
      -- do this until data is transferred, usually nothing
    end if;
  end if;
end process;



It's pretty obvious you aren't thinking like a hardware person, but are thinking like VHDL is software code. VHDL is a hardware description language and you should already know the circuit you want to design and what VHDL templates correspond to those hardware circuits. Go look at this on ASIC World for some templates of simple hardware circuits, i.e. FFs, muxes, decoders, etc.
 
Thank you for the response. My question now is won't the clock difference between the clk_adc and filter_clk mess things up? or is this wrong thinking from my side.

If that is the case that process would have to run on the filter clk (25M) correct ?
 

I won't expect that the ADC sample clock is actually represented as a design clock, more likely as a clock enable signal for the 25 MHZ design clock.
 
Pasted File at April 5, 2017 2-39 PM.png
I fully understand now. But won't this FIFO with independent clocks do the same as the solution mentioned above ?
(assuming slave = adc running at 48K , Master = filter = running at 25M)
 

But won't this FIFO with independent clocks do the same as the solution mentioned above ?
Yes, if there's actually a 48k clock. Reviewing post #1, the bad idea at the start is to drive the ADC module by a divided clock.

Instead of using a FIFO, you can still synchronize the 48 k into the 25M domain and convert it into a clock enable.
 

Yes, if there's actually a 48k clock. Reviewing post #1, the bad idea at the start is to drive the ADC module by a divided clock.

Instead of using a FIFO, you can still synchronize the 48 k into the 25M domain and convert it into a clock enable.

Why would it only work when it is an actual 48kHz clock and not one that is derived from the main clock? It is not like if there is a separate clock input that that one and the main clock will be exactly synchronous AFAIK.
 

Clocks derived from divide down counters in an FPGA will incur variable delay depending on both placement and routing of this divided down clock output. This will in turn result in variable setup and hod times that vary every time implementation is run, which is the primary reason it is considered a bad practice to create such clocks in the first place. By using a single clock design with an enable to only allow the slow logic to change state every 48KHz you avoid the issues with timing from the variably skewed clock network of the divided clock.

Besides this generating timing constraints to correctly constrain a divided down clock (being done in the FPGA fabric, instead of a PLL) will be required.
 

Why would it only work when it is an actual 48kHz clock and not one that is derived from the main clock?
I neither suggested an independent 48 kHz clock, it's just useless.
 
In AXI4, there is a requirement that the master (driving VALID) cannot wait for a slave to become ready. It is allowed for a slave to wait for VALID before asserting READY. This allows the slave to read the first word of input without needing to accept it on the same cycle, which can be useful in rare applications.

In practice, there are many Almost-Axi interfaces out there. For example, your design with fifo's has to assume READY is always 1 for the ADC fifo writes (and sets VALID to 1), and assumes VALID is always 1 for the DAC fifo reads (and sets READY to 1). At this point you are just connecting the axi-s interface to IP cores that were design to use them.



The choice to use a fifo in this design is based on where the 25MHz and 48kHz clocks come from. When the two clocks come from independent sources, the fifo is justified to avoid the need to emulate a PLL.

The choice for using the falling edge vs rising edge of the ADC clock is based on the IO requirements to the ADC and DAC. Low speed interfaces often have data output on the falling edge of the clock. When setup is very easy to meet, this method will also make hold easy to meet.
 
Everybody , thank you for all the help and tips, greatly appreciated !

This is what I have now. going to work on the DAC side and see how it works.


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
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
 
entity ADC is
    port(
        clk_inadc   :   in  STD_LOGIC;
        clk_adc     :   out     STD_LOGIC;
        adc_OF      :   in  STD_LOGIC;
        adc_in      :   in  STD_LOGIC_VECTOR(11 downto 0);
        adc_out     :   out     STD_LOGIC_VECTOR(15 downto 0) := (others => '0');
        adc_tvalid  :   out     STD_LOGIC := '0';
        adc_tready  :   in      STD_LOGIC;
        clk50           :   in  STD_LOGIC
        );
end ADC;
 
architecture ADC of ADC is
--signal adc_in_buff    :   STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
signal clk48kHz_f   :   STD_LOGIC := '0';
signal clk48kHz_ff  :   STD_LOGIC := '0';
signal adc_valid        :   STD_LOGIC := '0';
begin
    process(clk50)
    begin
    if rising_edge(clk50) then
        if adc_valid = '1' then
            adc_out(11 downto 0) <= adc_in;
        end if;
    end if;
    end process;
    
    process(clk50)
    begin
    if rising_edge(clk50) then
        clk48kHz_f <= clk_inadc;
        clk48kHz_ff <= clk48kHz_f;
        adc_valid <= clk48kHz_f and (not clk48kHz_ff); 
    end if;
    end process;
clk_adc <= not clk_inadc;   
adc_tvalid <= adc_valid when adc_tready ='1' else '0';
end ADC;

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top