Forum Discussion
Altera_Forum
Honored Contributor
12 years agoSimple interfacing between Avalon MM Slave and ARM HPS
Hi all, I'm trying to create a simple example of a master-slave communication between the onboard HPS (running Linux) and the FPGA fabric using a Cyclone V. The method I've followed so far is ...
Altera_Forum
Honored Contributor
10 years agoI am now able to read and write 32 bit words using the lightweight HPS to FPGA bridge!
Attaching my code if it might be useful to anyone: - I have defined a custom Avalon slave defined as follows below. Whenever read, it sends 32'hA5A5A5A5 as the readdata [31:0].module scratch_slave_32_bits_rw ( // No conduit
input clk,
input reset,
input read,
output reg readdata,
input write,
input writedata,
output reg hps_to_fpga_32_bits //conduit
);
reg arbitrary_constant = 32'hA5A5A5A5;
always@(posedge clk) begin
if(read) readdata <= arbitrary_constant;
else if (write) hps_to_fpga_32_bits <= writedata;
end
endmodule Top level module is as follows below. I am connecting the top 4 MSB's sent from the HPS to the LEDs on the DE0-Nano-SoC board. module quartus_scratch_1(
input CLOCK_50,
output led_values,
output hps_memory_mem_a,
output hps_memory_mem_ba,
output hps_memory_mem_ck,
output hps_memory_mem_ck_n,
output hps_memory_mem_cke,
output hps_memory_mem_cs_n,
output hps_memory_mem_ras_n,
output hps_memory_mem_cas_n,
output hps_memory_mem_we_n,
output hps_memory_mem_reset_n,
inout hps_memory_mem_dq,
inout hps_memory_mem_dqs,
inout hps_memory_mem_dqs_n,
output hps_memory_mem_odt,
output hps_memory_mem_dm,
input hps_memory_oct_rzqin
);
wire hps_to_fpga_32_bits;
assign led_values = hps_to_fpga_32_bits;
soc_system soc_system_inst_1(
.clk_clk(CLOCK_50), // clk.clk
.memory_mem_a(hps_memory_mem_a), // memory.mem_a
.memory_mem_ba(hps_memory_mem_ba), // .mem_ba
.memory_mem_ck(hps_memory_mem_ck), // .mem_ck
.memory_mem_ck_n(hps_memory_mem_ck_n), // .mem_ck_n
.memory_mem_cke(hps_memory_mem_cke), // .mem_cke
.memory_mem_cs_n(hps_memory_mem_cs_n), // .mem_cs_n
.memory_mem_ras_n(hps_memory_mem_ras_n), // .mem_ras_n
.memory_mem_cas_n(hps_memory_mem_cas_n), // .mem_cas_n
.memory_mem_we_n(hps_memory_mem_we_n), // .mem_we_n
.memory_mem_reset_n(hps_memory_mem_reset_n), // .mem_reset_n
.memory_mem_dq(hps_memory_mem_dq), // .mem_dq
.memory_mem_dqs(hps_memory_mem_dqs), // .mem_dqs
.memory_mem_dqs_n(hps_memory_mem_dqs_n), // .mem_dqs_n
.memory_mem_odt(hps_memory_mem_odt), // .mem_odt
.memory_mem_dm(hps_memory_mem_dm), // .mem_dm
.memory_oct_rzqin(hps_memory_oct_rzqin), // .oct_rzqin
.scratch_slave_32_bits_rw_0_conduit_end_export(hps_to_fpga_32_bits) // scratch_slave_one_byte.export
);
endmodule Finally, my C program running in the HPS is as follows:- #include <sys/mman.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <stdint.h>
# include "hps.h"
# include <time.h>
# include "socal.h"
# define HW_REGS_BASE (0xfc000000)
# define HW_REGS_BASE (0xfc000000)
# define HW_REGS_SPAN (0x04000000)
# define HW_REGS_MASK (HW_REGS_SPAN-1)
# define RW_SLAVE_OFST 0x00000000
volatile uint32_t *custom_slave_rw;
void *virtual_base;
int main()
{
int fd;
if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
printf( "ERROR: could not open \"/dev/mem\"...\n" );
return( 1 );
}
virtual_base = mmap(NULL, HW_REGS_SPAN, (PROT_READ|PROT_WRITE), MAP_SHARED, fd, HW_REGS_BASE);
if( virtual_base == MAP_FAILED ) {
printf( "ERROR: mmap() failed...\n" );
close( fd );
return( 1 );
}
custom_slave_rw = (uint32_t*)(virtual_base + ( (ALT_LWFPGASLVS_OFST + RW_SLAVE_OFST) & (HW_REGS_MASK)));
uint32_t read_value = *custom_slave_rw;
printf("Value read = 0x%08x\n",read_value); //READ 32--BIT-WORD FROM FPGA
uint32_t write_value = 0x69696969;
custom_slave_rw = write_value; //WRITE 32-BIT-WORD INTO FPGA
printf("Value written = 0x%08x\n\n",write_value);
cleanup:
if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) {
printf( "ERROR: munmap() failed...\n" );
close( fd );
return( 1 );
}
close(fd);
return 0;
Regards, Akshay