November 29, 2024

Antminer S9 board - Vivado -- blink the four board LEDs - round 2

We made a first attempt at doing this with EMIO and failed. Read the details here: I am going to take a different approach this time, trying to use the same scheme as this fellow did to blink a single LED: I won't give all the vivado details here. Refer to round 1 above for those. The first thing I do is to get rid of the project from round 1:
cd /home/tom/vivado
rm -rf s9_leds

A new approach

I launch vivado, create the s9_leds project again, add the zynq processing system to my empty block diagram and I am ready to try something new.

I customize the Zynq block by double clicking on it. First I disable the AXI GPIO that comes enabled by default. This gets rid of the clock input that caused issues during my last effort. To do this I select PS-PL configuration, then dig around in that under AXI non-secure until I find a GPIO check box to disable.

Second I enable GPIO to EMIO at a width of 4. I double click again, find MIO configuration, IO peripherals and then under GPIO, find EMIO and select a width of 4.

I right click on the GPIO_0 text on the Zynq block and select "create interface port" on the menu. Now I save the block design.

I go to "Design sources" under sources and click on "design 1", then select "create HDL wrapper" from the menu. I leave it set to "let Vivado manage sources".

Now we do "Run Synthesis". I get a popup and select "Cancel". I see at the upper right that Vivado is still busy. When it actually finishes I get another popup titled "Synthesis completed". I select "open synthesized design" and click OK.

On the far left, under Synthesis, we can find "Schematic" at the bottom of the expanded design. We click on that and things get interesting. I see a schematic with 4 blocks labeled "GPIO_0_tri_iobuf_x" where x is 0,1,2,3. Their outputs are bussed together as GPIO_0_tri_io[3:0].

At the top it says "134 I/O Ports". I click on that and get a scrollable thing in the bottom pane below the schematic. We scroll down to the bottom and find our four GPIO_0_tri_io[] ports.

The game now is to first set the I/O Std column for all 4 of these to LVCMOS33, then we set the "Package Pin" column as follows:

GPIO_0_tri_io[3]	F16		(silkscreen D7)
GPIO_0_tri_io[2]	L19		(silkscreen D8)
GPIO_0_tri_io[1]	M19		(silkscreen D5)
GPIO_0_tri_io[0]	M17		(silkscreen D6)
The Tutorial I am following tells me to "save project" here, but there is no such option available. There is "Save as", but that invents a new project name, in this case "project_1" I go with that and see the message:
INFO: [Project 1-96] Target constrs file set to
'/u1/home/tom/vivado/project_1/project_1.srcs/constrs_1/new/design_1_wrapper.xdc' for the 'constrs_1' constraints set.
I check and there is no such path or file in my project (s9_leds), so I exit vivado to see if that will save the project. I exit Vivado, but that doesn't yield a constraint file either. The tutorial I am following does not indicate a Vivado version he is using. The constraint file it did save in "project_1" is as follows:
set_property PACKAGE_PIN F16 [get_ports {GPIO_0_tri_io[3]}]
set_property PACKAGE_PIN L19 [get_ports {GPIO_0_tri_io[2]}]
set_property PACKAGE_PIN M19 [get_ports {GPIO_0_tri_io[1]}]
set_property PACKAGE_PIN M17 [get_ports {GPIO_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {GPIO_0_tri_io[0]}]
Aha! The big trick is the name GPIO_0_tri_io[] for the EMIO ports. Knowing this I can just set up my own constraint file and start over using it.

Drop back and use a constraint file

Now that we know the secret name for the EMIO GPIO signals, I add them to my "official" S9 constraint file, use "Add sources" to add that constraint to the project and I am ready to start over.

I type "update hierarchy", then repat "Run Synthesis". My little cheat sheet documents the order for a project as:

Generate block design
Run synthesis
Run implementation (skip "open implemented design"
Generate bitstream
Run the design
The synthesis completes without errors. I get a popup and change the radio box to "run implementation" and click OK.

The implementation completes without errors. I change the radio box selection to "generate bitstream" and type OK.

Bitstream generation finishes without errors.

Where is the bitstream?

It is here:
/u1/home/tom/vivado/s9_leds/s9_leds.runs/impl_1/design_1_wrapper.bit

Testing this

I am working on my Kyu RTOS and adding drivers, so I add some code to my gpio driver to support EMIO. Then I add a file pl.c from some bare metal code I wrote that loads a bitstream from the PS side of the Zynq. Then I compile it all up (including the latest bitstream) and write a quick bit of test code to blink LED and --- it works!!

Conclusions and discussion

I wanted to learn how EMIO worked in the world of Vivado. To be honest, I am disappointed. What if I want to use 4 bits of EMIO for the on-board LED like this and several other bits for some other purpose, routing them say to some RTL block with verilog in it? How can I do that? What if I want to use several groups of EMIO signals for entirely different purposes?

Also remember that there are 3 sets of EMIO signals. We have 64 bits of data out, another 64 bits of "direction" out, and 64 bits of data in. 192 bits in all. Once I select 4 bits in the menu to customize Zynq IP, I have no other options.


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org