I'm woring on a project for an assingment where I need to be able write data to an avalon slave module to select data from 2 different inputs on a nios system running on a DE0 board. After much toiling, I've been unable to write data from the C app running on the nios core to the avalon slave. I have verified that I'm able to read data from the slave by using some hard coded values. I have also verified that my app is running because I'm seeing the messages I expect over the jtag uart, and the push buttons, LEDs and LED display work as expected.
I have simplified my slave so that data I write to it is then read straight back. The VHDL code is:
library ieee;
use ieee.std_logic_1164.all;
USE IEEE.NUMERIC_STD.ALL;
entity FIFO_Control is
port (clk : IN std_logic;
reset : IN std_logic;
read : IN std_logic;
readdata : OUT std_logic_vector(7 DOWNTO 0);
write : IN std_logic;
writedata : IN std_logic_vector(7 DOWNTO 0);
din1 : in std_logic_vector(4 DOWNTO 0);
din2 : in std_logic_vector(4 DOWNTO 0)
);
end FIFO_Control;
architecture FIFO_CTRL of FIFO_Control is
signal int_data : std_logic_vector(7 DOWNTO 0) := "00000000"; -- a hard coded test value to check the read works
begin
with (write) SELECT
int_data <= writedata when '1',
"01010101" when others;
readdata <= int_data;
end FIFO_CTRL;
The C code is
#include "sys/alt_stdio.h"
#include <altera_avalon_timer_regs.h>
#include <altera_avalon_pio_regs.h>
#include <system.h>
#include "Sch51.h"
#include "serial.h"
#include "seven_seg.h"
#define SEVEN_SEGMENT_0_BASE 0x1001080
#define LED_BASE (0x01001070)
#define LED0_pin (0x01)
#define LED1_pin (0x01 << 1)
#define LED2_pin (0x01 << 2)
#define LED3_pin (0x01 << 3)
#define PIO_1_BASE 0x0
#define BUTTON_BASE PIO_1_BASE
#define BUTTON0 0x01
#define BUTTON1 0x02
#define FIFO_CTRL_0_BASE 0x1001090
void LED_Flash_Update(void)
{
static count = 0;
alt_u8 read;
IOWR_8DIRECT(FIFO_CTRL_0_BASE, 0, 0);
read = IORD_8DIRECT(FIFO_CTRL_0_BASE, 0);
Serial_Printf("FIFO1: %d\r\n", read);
IOWR_8DIRECT(FIFO_CTRL_0_BASE, 0, 1);
read = IORD_8DIRECT(FIFO_CTRL_0_BASE, 0);
Serial_Printf("FIFO1: %d\r\n", read);
// Change the LED from OFF to ON (or vice versa)
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) ^ LED3_pin);
if (count < 10)
{
count++;
}
else if ((count >= 10) && (count < 100))
{
count += 10;
}
else if ((count >= 100) && (count < 1000))
{
count += 100;
}
else if ((count >= 1000) && (count < 10000))
{
count += 1000;
}
else
{
count = 0;
}
seven_seg_store_number(SEVEN_SEGMENT_0_BASE, 0, 9999, 10, count);
if ((IORD_ALTERA_AVALON_PIO_DATA(BUTTON_BASE) & BUTTON0) == 0)
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) | LED0_pin);
}
else
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) & ~LED0_pin);
}
if ((IORD_ALTERA_AVALON_PIO_DATA(BUTTON_BASE) & BUTTON1) == 0)
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) | LED1_pin);
}
else
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,
IORD_ALTERA_AVALON_PIO_DATA(LED_BASE) & ~LED1_pin);
}
}
int alt_main()
{
alt_u8 read;
SCH_Init_T0();
serial_Init();
SCH_Add_Task(serial_Update, 0, 10);
SCH_Add_Task(LED_Flash_Update, 0, 1000);
// Start the scheduler
SCH_Start();
Serial_Puts("EHMC AJE System Running\n");
/* Event loop never exits. */
while (1)
{
SCH_Dispatch_Tasks();
}
return 0;
}
I'm not able to see why I'm not able to write anything to the avalon slave "Fifo_control". Can someone suggest what the problem is please?
If you look at the port declarations on your entity/component and then at your code, you can already see that you are doing something wrong, as you are not using all the port.
So your problem states that you want to write data to your Avalon slave. So you want the component to remember the data you've written (i.e. memory). But there is no memory component in your code. There's just a combinatorial expression.
When designing an Avalon component, you should read the Avalon Interface Specification.
So reading the document, you see that you should have a process/statement for the write port and a process for the read port. Each takes a clock cycle to process (if the read latency is 1). E.g.
write_proc: process(clk) begin
if rising_edge(clk) then
if write = '1' then
int_data <= writedata;
end if;
-- reset statement
if reset = '1' then
int_data <= (others => '0');
end if;
end if;
end process;
read_proc: process(clk) begin
if rising_edge(clk) then
if read = '1' then
readdata <= int_data;
end if;
-- reset statement
if reset = '1' then
readdata <= (others => '0');
end if;
end if;
end process;