Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to configure UART for PL part of Zynq-7000 FPGA??

Status
Not open for further replies.

msdarvishi

Full Member level 4
Joined
Jul 30, 2013
Messages
230
Helped
1
Reputation
2
Reaction score
1
Trophy points
18
Activity points
2,349
Dear all,

I am using Vivad0 2017.1 on a Window 7-64bit laptop targeting a Zynq-7000 (xc7z020clg484-3) FPGA

I have a design that includes a 16-bits counter implemented successfully in the PL part of the FPGA. Based on the description in page 13 of zedboard user guide here, we know that UART 1 is already connected to the PS part of device which means there will be no connection from PL part to this UART. Please correct me if I am wrong !

Now, I want to send the output of my counter that are 16 bits to the UART port and read the counted values with a terminal (PuTTY, Tera term, Hyperterminal, etc). I searchd a lot about this issue even the Hell world project that was written in C language and is run in SDK !!! I am pretty confused !!

Something that I have done untill now, is shown in the attached snapshot. I have generated the IP core AXI UART16550 as an Out-of-context module along with mu top file (top file includes my counter). But after synthesis and implementation, I do not see the UART module and I do not know how should I define the outputs of counter to be sent to the UART and what constraints are required to make the UART run and send the counted values to the PC to be seen in terminal???

I am wondering if someone can guide me step by step to solve this issue. I am new to Zedboard. I also have read some post regarding enabling UART 0 in zedboard like here, but it's again written in C language while I have VHDL files for my counter !!!

Kind replies and helps are in advance appreciated.

Regards, Capture.PNG
 

Rather than a complex AXI interfaced UART with FIFO, a simple VHDL UART design together with a state machine generating the multi byte data packet should be sufficient. There are many previous Edaboard threads about HDL UART design and much more available on the internet. Just google "VHDL UART".
 

Something that I have done untill now, is shown in the attached snapshot. I have generated the IP core AXI UART16550 as an Out-of-context module along with mu top file (top file includes my counter). But after synthesis and implementation, I do not see the UART module and I do not know how should I define the outputs of counter to be sent to the UART and what constraints are required to make the UART run and send the counted values to the PC to be seen in terminal???

From the screenshot it is apparent that you have just generated the IP core AXI UART16550 and have added it to the project. Where have you done the actual connection of the IP with the module that would generate the data to be transmitted?

Keep aside the counter idea for now.
There are many tutorials as how "Hello World" can be printed at Putty/HyperTerminal using an AXI UART running on the FPGA. Implement that and study it. One you fully understand how the AXI UART exchanges data via the AXI i/f, then go for your counter implementation.

If you are scared about the complexities of AXI and C code running on a processor, you should follow what FvM says in #2.

Here is a helpful step by step:
https://reference.digilentinc.com/l...basys-3-getting-started-with-microblaze/start
 
Last edited:

I understood that msdarvishi is looking for a solution without embedded processor. Although AXI bus interface can be used in a pure hardware (HDL coded) design, it doesn't make much sense for the present problem.
 

There is also the little issue about sending a counter value to the UART, the OP is expecting to see numbers on their terminal (i.e. ASCII)
so...
a) they have to convert the binary numbers into ASCII.
b) be stuck with unreadable symbols

The primary problem with the initial attempt at the design is they don't have the axi_uart16550_0 instantiated in the top.vhd file, so the uart is not even part of the design.

If the plan was to use the UART0 IP peripheral (you don't create an IP core with the core generator) then you would likely need to build a PS system and connect an AXI master to the counter (all in a custom IP design) to be able to access the UART0, though I'm not entirely sure this will work. I haven't worked with Zynq, but have read over some of the documentation over the years.
 

From the screenshot it is apparent that you have just generated the IP core AXI UART16550 and have added it to the project. Where have you done the actual connection of the IP with the module that would generate the data to be transmitted?

Keep aside the counter idea for now.
There are many tutorials as how "Hello World" can be printed at Putty/HyperTerminal using an AXI UART running on the FPGA. Implement that and study it. One you fully understand how the AXI UART exchanges data via the AXI i/f, then go for your counter implementation.

If you are scared about the complexities of AXI and C code running on a processor, you should follow what FvM says in #2.

Here is a helpful step by step:
https://reference.digilentinc.com/l...basys-3-getting-started-with-microblaze/start

Hello,

Thanks for your great hint. I did the HelloWorld project step-by-step on the Zedboard using the zynq processing system. I could communicate between PS and PL and the Hello world works very nice ! :)) But I do not know how to employ this processing system and UART communication in order to read and send the values of my counter to the UART port?!! Do you have any idea??

Thanks,
 

Good, now that you know how to use make use of the UART and controlling it via s/w, this is what you can try.

1. Store the counter values in a register.
2. Make this reg readable by the zynq processing system (connect the reg to the bus).
3. Write C code to read this reg (at regular intervals) and send the read-out value/values to the UART.
4. So just as "Hello Word" is seen in the terminal, so should be the reg value/values (if everything is done properly).
Done! :)
 
Last edited:

Good, now that you know how to use make use of the UART and controlling it via s/w, this is what you can try.

1. Store the counter values in a register.
2. Make this reg readable by the zynq processing system (connect the reg to the bus).
3. Write C code to read this reg (at regular intervals) and send the read-out value/values to the UART.
4. So just as "Hello Word" is seen in the terminal, so should be the reg value/values (if everything is done properly).
Done! :)


Dear @dpaul,
Thanks for your reply. I did the step 1 of your suggestion. My output is a 16 bits vector signal that I want to make it readable by processor. This is my question, I do not know how to put this sifnal (register) on the bus? On which bus should I put it? Is it the AXI bus? In the following block diagam of design, I activated the GPIO2 as a custom port and I was trying to put my 16 bit output signal (prd[15:0]) on it, but I cannot do that since prd is a output port and GPIO2 is an inout port that brings a conflict !!! Can you please help me to recognize the correct bus in order to load my signal on it?

I also instantiated the HDL wrapper file (zynq_design_1_wrapper entity) as a component in my top file that also includes my counter. I do not know is it necessary to do or not?



Thanks,
 

Attachments

  • zynq_design_1.pdf
    65 KB · Views: 197

make the GPIO an input only then. you can double click on the axi_gpio_0 block and change direction of the GPIO ports.
 

make the GPIO an input only then. you can double click on the axi_gpio_0 block and change direction of the GPIO ports.

Thanks for your reply. It does not work even after defining the GPIO as an "input" port or even as a "buffer" ! while my 16-bit output of counter is defined once as an "output" and then as a "buffer". All those trials have been failed due to the following error:

Code:
[DRC MDRV-1] Multiple Driver Nets: Net zynq_processor/gpio_rtl_tri_iobuf_0/IO has multiple drivers: zynq_processor/gpio_rtl_tri_iobuf_0/OBUFT/O, and prd_contr/p_reg_reg[0]/Q.
 

Why do you have a tristate iobuffer on the net? I think you've specified the GPIO incorrectly and designated it as an output pin when it should only be an external port. I'm assuming that the prd_contr is instantiated outside this block design in a top/wrapper file as there is not a prtd_contr in the bd.

You probably specified the wrong dual channel GPIO interface as the input and output (the other one looks like it connects to some LEDs).

Here is an example done under 2016.2 with just a Zynq and a dual channel GPIO.
View attachment design_1.zip
This produces the following top level .v file:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//Copyright 1986-2016 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2016.2 (win64) Build 1577090 Thu Jun  2 16:32:40 MDT 2016
//Date        : Thu Aug 17 13:09:32 2017
//Command     : generate_target design_1.bd
//Design      : design_1
//Purpose     : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps
 
(* CORE_GENERATION_INFO = "design_1,IP_Integrator,{x_ipVendor=xilinx.com,x_ipLibrary=BlockDiagram,x_ipName=design_1,x_ipVersion=1.00.a,x_ipLanguage=VERILOG,numBlks=6,numReposBlks=4,numNonXlnxBlks=0,numHierBlks=2,maxHierDepth=0,numSysgenBlks=0,numHlsBlks=0,numHdlrefBlks=0,numPkgbdBlks=0,bdsource=USER,da_axi4_cnt=1,da_board_cnt=2,synth_mode=Global}" *) (* HW_HANDOFF = "design_1.hwdef" *) 
module design_1
   (DDR_addr,
    DDR_ba,
    DDR_cas_n,
    DDR_ck_n,
    DDR_ck_p,
    DDR_cke,
    DDR_cs_n,
    DDR_dm,
    DDR_dq,
    DDR_dqs_n,
    DDR_dqs_p,
    DDR_odt,
    DDR_ras_n,
    DDR_reset_n,
    DDR_we_n,
    gpio_rtl_0_tri_i,
    gpio_rtl_tri_i,
    gpio_rtl_tri_o,
    gpio_rtl_tri_t);
  inout [14:0]DDR_addr;
  inout [2:0]DDR_ba;
  inout DDR_cas_n;
  inout DDR_ck_n;
  inout DDR_ck_p;
  inout DDR_cke;
  inout DDR_cs_n;
  inout [1:0]DDR_dm;
  inout [15:0]DDR_dq;
  inout [1:0]DDR_dqs_n;
  inout [1:0]DDR_dqs_p;
  inout DDR_odt;
  inout DDR_ras_n;
  inout DDR_reset_n;
  inout DDR_we_n;
  input [31:0]gpio_rtl_0_tri_i;  // NOTE this is an input only!
  input [31:0]gpio_rtl_tri_i;   // Bi-directional on LED (should have been output only, oh well)
  output [31:0]gpio_rtl_tri_o;  // bi-directional output
  output [31:0]gpio_rtl_tri_t;  // bi-directional output tri-state
 
// rest of file deleted as unimportant to the answer


Capture.PNG
As you can see the gpio_rtl_0 port is an input only.
 
Good, now that you know how to use make use of the UART and controlling it via s/w, this is what you can try.

1. Store the counter values in a register.
2. Make this reg readable by the zynq processing system (connect the reg to the bus).
3. Write C code to read this reg (at regular intervals) and send the read-out value/values to the UART.
4. So just as "Hello Word" is seen in the terminal, so should be the reg value/values (if everything is done properly).
Done! :)

Hello,

Fortunately, I could activate the PS part (ARM Core) of Zynq-7000 (CLG484) board and created a simple register via SDK tool and I could communicate with it via the processor. I used the PlanAhead in order to do it. Since I had some design constraints in vivado written in XDC format, now the PlanAhead only accepts the UCF file !! I do not know how can I apply my constraints into the design?? Notice that some of my constraints are not translatable to UCF for example the constraint for routings that I made them already in my XDC file in Vivado design.

Do you have any idea??

Thanks and Regards,

- - - Updated - - -

Why do you have a tristate iobuffer on the net? I think you've specified the GPIO incorrectly and designated it as an output pin when it should only be an external port. I'm assuming that the prd_contr is instantiated outside this block design in a top/wrapper file as there is not a prtd_contr in the bd.

You probably specified the wrong dual channel GPIO interface as the input and output (the other one looks like it connects to some LEDs).

Here is an example done under 2016.2 with just a Zynq and a dual channel GPIO.
View attachment 140620
This produces the following top level .v file:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//Copyright 1986-2016 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2016.2 (win64) Build 1577090 Thu Jun  2 16:32:40 MDT 2016
//Date        : Thu Aug 17 13:09:32 2017
//Command     : generate_target design_1.bd
//Design      : design_1
//Purpose     : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps
 
(* CORE_GENERATION_INFO = "design_1,IP_Integrator,{x_ipVendor=xilinx.com,x_ipLibrary=BlockDiagram,x_ipName=design_1,x_ipVersion=1.00.a,x_ipLanguage=VERILOG,numBlks=6,numReposBlks=4,numNonXlnxBlks=0,numHierBlks=2,maxHierDepth=0,numSysgenBlks=0,numHlsBlks=0,numHdlrefBlks=0,numPkgbdBlks=0,bdsource=USER,da_axi4_cnt=1,da_board_cnt=2,synth_mode=Global}" *) (* HW_HANDOFF = "design_1.hwdef" *) 
module design_1
   (DDR_addr,
    DDR_ba,
    DDR_cas_n,
    DDR_ck_n,
    DDR_ck_p,
    DDR_cke,
    DDR_cs_n,
    DDR_dm,
    DDR_dq,
    DDR_dqs_n,
    DDR_dqs_p,
    DDR_odt,
    DDR_ras_n,
    DDR_reset_n,
    DDR_we_n,
    gpio_rtl_0_tri_i,
    gpio_rtl_tri_i,
    gpio_rtl_tri_o,
    gpio_rtl_tri_t);
  inout [14:0]DDR_addr;
  inout [2:0]DDR_ba;
  inout DDR_cas_n;
  inout DDR_ck_n;
  inout DDR_ck_p;
  inout DDR_cke;
  inout DDR_cs_n;
  inout [1:0]DDR_dm;
  inout [15:0]DDR_dq;
  inout [1:0]DDR_dqs_n;
  inout [1:0]DDR_dqs_p;
  inout DDR_odt;
  inout DDR_ras_n;
  inout DDR_reset_n;
  inout DDR_we_n;
  input [31:0]gpio_rtl_0_tri_i;  // NOTE this is an input only!
  input [31:0]gpio_rtl_tri_i;   // Bi-directional on LED (should have been output only, oh well)
  output [31:0]gpio_rtl_tri_o;  // bi-directional output
  output [31:0]gpio_rtl_tri_t;  // bi-directional output tri-state
 
// rest of file deleted as unimportant to the answer


View attachment 140621
As you can see the gpio_rtl_0 port is an input only.

Dear ads-ee,

Thanks for your reply. The zip file of design_1 that you uploaded, containts a *.bd file. With which tool I can open and run it??

Regards,
 

It's a Vivado 2016.2 block design file, you just add it as a source file.

I assumed you knew what kind of file it was as you included a pdf of a bd in #8.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top