Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Comunicados
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Custom Component

Altera_Forum
Colaborador honorário II
1.379 Visualizações

Hi, 

 

I created a 2-FIFOs with the following ports 

 

clk 

aclr 

wr_en 

data_in 

rd_en 

data_out 

empty(only on the source FIFO) 

 

one fifo will be the source and another fifo will be the destination. I created a top level vhdl component which connected both fifo components together, and I made it into a custom component with the following mapping to the nios cpu 

 

--common 

clk->clock 

aclr->reset 

 

--source fifo 

wr_en ->export (source fifo) 

data_out ->export (source fifo) 

rd_en ->read (source fifo) 

data_in ->read_data (source fifo) 

empty ->dataavailable_n (source fifo) 

 

--destination fifo 

wr_en ->write (destination fifo) 

data_out ->write_data (destination fifo) 

rd_en ->export (destination fifo) 

data_in ->export (destination fifo) 

 

 

 

Here is what I want the NIOS proc to do. Pull in data only when dataavailable_n=0, then do math computation, then send it out to the other fifo. 

 

I wrote the C code which will pull the data in, do the math, and send it out to the other fifo, but I only want it to pull data in when dataavailable_n=0(which basically means the source fifo will send out data when there is something in there). How do I go about in doing this? Do I do this somewhere in the C code?
0 Kudos
5 Respostas
Altera_Forum
Colaborador honorário II
548 Visualizações

Good news, you have many options. They boil down to pulled and interrupt driven solutions. 

 

Since you are working with FIFOs it sounds like you want speed so I'll jump straight to the interrupt solution. If you take the component you created and use that dataavailable_n to trigger the interrupt that will be the method to alert the CPU data is ready. Then in your service routine you read in the value (and if your calculations are fast you may even want to do those and put the data into the transmit FIFO all within the interrupt service routine). 

 

Just so you know this isn't the highest performance way to do this with FIFOs though. You can increase your thoughput if you can afford to wait a while for the FIFO to fill up. What I mean is instead of firing off an interrupt every time data enters the fifo you wait until it's filled up to 50%, 75%,.....whatever as long as there is more than one word in there and your system will be fast enough to empty it. Then you trigger the interrupt off this "almost full" signal and start pulling that data out. A side note of this idea is that you can also DMA the data into a faster memory and crunch the numbers faster (really depends on your application though which idea works best). 

 

Hope that helps.
Altera_Forum
Colaborador honorário II
548 Visualizações

Thanks for your reply BadOmen, 

 

I like change my design to handle interrupts, I have a bit of a problem. I am a total noob with dealing with interrupts in C and how the interrupt signal should look like out of the VHDL code.  

 

Here is my VHDL code as of right now 

 

library ieee;  use ieee.std_logic_1164.all;  use IEEE.std_logic_unsigned.all; ENTITY top_log IS    port(        i_clk               : IN STD_LOGIC;        i_aclr              : IN STD_LOGIC;        i_source_data       : IN STD_LOGIC_VECTOR(31 DOWNTO 0);        i_source_wrreq      : IN STD_LOGIC;        i_cpu_rdreq         : IN STD_LOGIC;        o_cpu_i_data        : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);        o_cpu_wait_request  : OUT STD_LOGIC;        i_cpu_o_data        : IN STD_LOGIC_VECTOR(31 DOWNTO 0);        i_cpu_wrreq         : IN STD_LOGIC;        i_dest_rdreq        : IN STD_LOGIC;        o_dest_data         : OUT STD_LOGIC_VECTOR(13 DOWNTO 0);        o_dest_rdy_to_rd_n  : OUT STD_LOGIC        ); END top_log; ARCHITECTURE rtl OF top_log IS COMPONENT log_source_fifo     PORT     (  data  : IN STD_LOGIC_VECTOR (31 DOWNTO 0);  wrreq  : IN STD_LOGIC;  rdreq  : IN STD_LOGIC;  clock  : IN STD_LOGIC;  q  : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);  empty  : OUT STD_LOGIC     ); END COMPONENT; COMPONENT log_destination_fifo     PORT     (  data  : IN STD_LOGIC_VECTOR (31 DOWNTO 0);  wrreq  : IN STD_LOGIC;  rdreq  : IN STD_LOGIC;  clock  : IN STD_LOGIC;  q  : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);  empty  : OUT STD_LOGIC     ); END COMPONENT; SIGNAL c_dest_data : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL c_cpu_source_empty : STD_LOGIC; type sm_wait_request_type is (s_waitrequest_init, s_waitrequest_okay); signal sm_wait_request: sm_wait_request_type; BEGIN o_dest_data <= c_dest_data(13 DOWNTO 0); LOG_SOURCE : log_source_fifo PORT MAP (                                       data   => i_source_data,                                       wrreq  => i_source_wrreq,                                       rdreq  => i_cpu_rdreq,                                       clock  => i_clk,                                       q      => o_cpu_i_data,                                       empty  => c_cpu_source_empty                                      ); LOG_DESTINATION : log_destination_fifo PORT MAP (                                                 data   => i_cpu_o_data,                                                 wrreq  => i_cpu_wrreq,                                                 rdreq  => i_dest_rdreq,                                                 clock  => i_clk,                                                 q      => c_dest_data,                                                 empty  => o_dest_rdy_to_rd_n                                                ); sm_wait_request_machine: process (i_clk, i_aclr) begin if i_aclr=&#39;1&#39; then  sm_wait_request <= s_waitrequest_init;     o_cpu_wait_request <= &#39;0&#39;; elsif rising_edge(i_clk) then  case sm_wait_request is    when s_waitrequest_init =>      o_cpu_wait_request <= &#39;0&#39;;      if c_cpu_source_empty = &#39;0&#39; then        sm_wait_request <= s_waitrequest_okay;        o_cpu_wait_request <= &#39;1&#39;;      end if;    when s_waitrequest_okay =>      if i_cpu_wrreq = &#39;1&#39; then        sm_wait_request <= s_waitrequest_init;      end if;  end case; end if; end process; end RTL; 

 

Right now the waitrequest signal goes high once empty signal from the source fifo goes low and the waitrequest signal doesn not go down to 0 until the last piece of data is written into the destination fifo. I can change the code back so it will send a signal to the cpu to tell it data is ready as you suggested in the above post. 

 

here is my c code 

 

#include <stdio.h># include <math.h># include "system.h"# include "altera_avalon_pio_regs.h" int main (void) { double source_word; double log_word; double floor_word; double upscaled_word; while(1) { source_word = IORD(TOP_LOG_0_BASE, 0); log_word = 10*log10(source_word); upscaled_word = (log_word)*(pow(2,6)); floor_word = floor(upscaled_word); IOWR(TOP_LOG_0_BASE, 0 , floor_word); };   return 0; } 

 

This code is meant to convert MHz into Db(10log10(Mhz)) and upscaled 2^6 so I will get the precision I need. how would i change this code and mapping in the custom component to implement interrupts? 

 

 

Thanks in advance!
Altera_Forum
Colaborador honorário II
548 Visualizações

Actually now that I have seen your code I have a question. 

 

Is the Nios II in this system simply a stage in this FIFO train that does the db calculation? If so I have a simplier idea for you that involves pulling (interrupts are only useful if your system does many things where pulling is wasteful, but if you only perform one task then pulling is actually a better solution). 

 

Long story short in the pulling method I would have the empty/full status of your fifo be a register that you can read from to determine the status of your FIFOs. So for the input fifo if emtpy = 0 you don&#39;t read from it, and in your send fifo you wait for full = 0 to put data into it. If you are not sure how to create an external register space let me know and I can send you a dumb little design that I made which has 4 registers sitting in custom logic, and the processor can read/write to them.
Altera_Forum
Colaborador honorário II
548 Visualizações

it is only going to perform one task. at first i thought of using registers but seeing how taking a log of a number takes 300 us at 85MHz, another 2-3 pieces of data could be waiting to be pulled while the log is being done. 

 

yes, i would like to see your little design which will have the processor read/write to the registers when there is something in there. it would help me use it as an example.
Altera_Forum
Colaborador honorário II
548 Visualizações

oh yeah i almost forgot 

 

i got it working with IRQs, thank you for telling me about it. i&#39;ll use your method of using external registers space because you said its more efficient. looking forward for your example program. 

 

thanks again! 

 

patel
Responder