- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
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?Link copiado
5 Respostas
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
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.- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
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 nowlibrary 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='1' then
sm_wait_request <= s_waitrequest_init;
o_cpu_wait_request <= '0';
elsif rising_edge(i_clk) then
case sm_wait_request is
when s_waitrequest_init =>
o_cpu_wait_request <= '0';
if c_cpu_source_empty = '0' then
sm_wait_request <= s_waitrequest_okay;
o_cpu_wait_request <= '1';
end if;
when s_waitrequest_okay =>
if i_cpu_wrreq = '1' 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!
- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
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'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.- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
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.- Marcar como novo
- Marcador
- Subscrever
- Silenciar
- Subscrever fonte RSS
- Destacar
- Imprimir
- Denunciar conteúdo inapropriado
oh yeah i almost forgot
i got it working with IRQs, thank you for telling me about it. i'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
Opções do tópico
- Subscrever fonte RSS
- Marcar tópico como novo
- Marcar tópico como lido
- Flutuar este Tópico para o utilizador atual
- Marcador
- Subscrever
- Página amigável para impressora