- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 this: Firmware: - instantiate the HPS in Qsys with nothing but a LWH2F bridge - write a simple verilog module (flash_led.v) as an Avalon MM Slave (i.e. it has read, readdata, write, and writedata signals) and connect it to the HPS in Qsys - connect everything in a simple top-level verilog module and set the LED output pins to display whatever shows up on the writedata signal Software: - write a simple c program that deals with memory mapping via:int fd = open("/dev/mem", (O_RDWR|O_SYNC));
void* slave_base = mmap(NULL, ALT_LWFPGASLVS_SPAN, (PROT_READ|PROT_WRITE), MAP_SHARED, fd, (off_t)ALT_LWFPGASLVS_ADDR);
- also deal with writing to the slave peripheral via: volatile unsigned char* slave_addr = (unsigned char*)slave_base; // the offset of my flash_led component in Qsys is 0x0 so it can be ignored
*slave_addr = some_value;
This works for writing to the slave module (I see the LEDs set correctly), but I'm unable to read from it when I try things like "read_value = *slave_addr;" I've seen a few examples online which use the alt_write_word() and alt_read_word() functions, but I haven't been able to get these to do anything for me thus far... Do I need to be doing more with my Verilog module? Is the "address" signal necessary when reading and writing from an Avalon MM slave? I suspect I may have a conceptual misunderstanding of this whole bridging process... Can anyone help me out or point me in the right direction? For reference, here's the simple flash_led.v verilog module I've been using: module flash_led
(
input clock,
input reset_n,
input write,
input writedata,
input read,
output readdata,
output led
);
reg led_internal;
reg stupidconstant = 8'b01010101;
assign led = led_internal;
assign readdata = stupidconstant;
always @(posedge clock) begin
if (!reset_n)
led_internal <= 4'b0000;
else if (write) begin
led_internal <= writedata;
end
end
endmodule
John
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can anyone help me out with this? I've been stuck on the same issue for a few days now... Even if it's just a nudge in the right direction - I'd be happy to know just if my problem is in the software or the firmware.
Thanks, John- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, I solved it. In case anyone has the same confusion, here's the essential parts of the software that I was missing:
This might be overkill, but it works if you just map the entire hardware register space into virtual memory:#define HW_REGS_BASE ALT_STM_OFST
# define HW_REGS_SPAN 0x04000000
# define HW_REGS_MASK (HW_REGS_SPAN-1)
Also, I needed to find the address offset of my module that I added as a component to Qsys (read this from the address map) #define MY_MODULE_OFST 0x00000000
Then, ignoring error checking, I took care of memory mapping like this: int virtual_base;
int fd;
fd = open("/dev/mem", (O_RDWR|O_SYNC));
virtual_base = mmap(NULL, HW_REGS_SPAN, (PROT_READ|PROT_WRITE), MAP_SHARED, fd, HW_REGS_BASE);
Finally, reading and writing worked with: alt_write_word(virtual_base + ((ALT_LWFPGASLVS_OFST + MY_MODULE_OFST) & HW_REGS_MASK), write_val);
read_val = alt_read_word(Virtual_base + ((ALT_LWFPGASLVS_OFST + MY_MODULE_OFST) & HW_REGS_MASK));
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
can you explain me what shout I set ALT_STM_OFSET ? In "HW_REGES_SPAN" is a span of particular component of IP core or span of HPS LWFPGASLAVES ? What is use of "HW_reges_mask" ? Please help me,I don't have experience to work with Hard processor system ans also don't have much experience to work with Linux..- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am stuck with the same problem as well. I am able to write data from the HPS to the FPGA, but not able to read data back from the FPGA into the HPS. I am using the Lightweight HPS to FPGA bridge in Cyclone V. I have defined an Avalon-MM slave as follows: -module scratch_slave_one_byte(
input clk,
input reset,
input write,
input writedata,
input read,
output reg readdata,
output reg byte_from_hps,
output write_count_w,
input byte_into_hps
);
reg write_count = 0;
assign write_count_w = write_count;
always@(posedge clk) begin
if (write) begin
byte_from_hps <= writedata;
end
else if (read) readdata <= byte_into_hps ;
end
endmodule
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 ALT_LWFPGASLVS_OFST 0xff200000
# define HW_REGS_BASE (0xfc000000)
# define HW_REGS_SPAN (0x04000000)
# define HW_REGS_MASK (HW_REGS_SPAN-1)
# define MY_MODULE_OFST 0x00000000
# define WRITE 0x00
# define READ 0x04
volatile unsigned char* custom_slave;
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 = (unsigned char*)(virtual_base + ( (ALT_LWFPGASLVS_OFST + MY_MODULE_OFST + WRITE) & (HW_REGS_MASK)));
custom_slave = 0x06; //WRITE BYTE INTO FPGA
unsigned char value = custom_slave; //READ BYTE FROM FPGA
printf("%d\n",value);
//value = alt_read_word(virtual_base + ((ALT_LWFPGASLVS_OFST + MY_MODULE_OFST) & HW_REGS_MASK));
//printf("%d\n",value);
cleanup:
if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) {
printf( "ERROR: munmap() failed...\n" );
close( fd );
return( 1 );
}
close(fd);
return 0;
}
I connect the readdata [7:0] inputs to 8'b00000011 in the top level module. However, the signal I read into the HPS is always zero. Any help would be great. Thanks! Akshay
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Akshay, Im using your code to test. But I have an error. {Port "scratch_slave_32_bits_rw_0_conduit_end_export" does not exist in macrofunction "soc_system_inst_1"}. Do you have any idea ? Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hey,
1) Please check if you included the Avalon slave in the Qsys component. 2) Check if you have exported the port "scratch_slave_32_bits_rw_0_conduit_end_export" as Conduit in the Avalon slave Qsys component. You could use this well explained blog for reference: https://zhehaomao.com/project/2014/01/02/fpga-series.html Regards, Akshay- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Akshay !
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I really don't get why HW_REGS_BASE (0xfc000000) must be used?!
Can anybody explain this? This is the Base Address of the Coresight System Trace Macrocell or not?! cant we mmap the ALT_LWFPGASLVS_OFST instead?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi to every one! I'm attempting to do something similar to this question.. I want read/write QSYS on chip memory dual access from HPS running a C app under Linux
I make a bootable sd card with angstrom 2018.06 and it runs fine on my self-developed card with CycloneV Soc (!! hard work but it is done!!)
So, I connected DS-5 V29 to my card via remote system SH Connection, it works fine following Hello Word for Linux app tutorial!! DS-5 woks well.
Then I search to access to ONCHIP mem follwoing examples from LED access as you show here ! Virtual memory access and so on
MY PROBLEM is to determine a valid environment IN DS-5 to do it, in terms of libs to include!!!! THERE IS A BUNCH of mman.h, fcntl,h etc etc.. they are under my Linaro distro spl directory
- If I use GCC compiler , I obtain errors on valid simple code C and I must use ARM-5 compiler
- Then, I use ARM-5 compiler, but it doenst' find std.io basic libraries, options 0_SYNC and other options in mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0) are not acks correctly
- THERE IS A OVERVIEW OR A MANUAL TO CREATE A RELIABLE DS-5 ENVIRONMENT to works fine writing HPS C APP???? It is difficult to link and search a bunch of libraries without a guide! Linux libs for mman.h are interconnetcted and so cannot be simply copied under the project folder, but probavly they must set as path..
- I cannot find any tutorial about this issue!
Do you have solved this bunch?
Thanks in advance for any suggestion!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page