CMPE 415 UMBC
Prof. Ryan Robucci
Assigned Sept 11, 2018; Due Sept 18, 2017; students working in identified pairs are allowed to collaborate without restriction on this assignment but each students should install the software and complete steps on their computer and submit independently. Submission instructions are TBD, but expect them soon (back up your work in the meantime).
The objective of this lab is to learn the fundamental components of the Xilinx FGPA tools required to enter and assemble HDL code using a schematic entry tool and program an FPGA. This includes integrating HDL into a schematic, as well as creating and updating symbols.
In this lab you will program an FPGA to display a rectangle on a monitor using a VGA cable. You will first create an implementation with an error in it and view the results. You will then modify the code, update the symbol in the schematic, and wire the schematic correctly to control the color of the rectangle using switches.
source /tank/opt/Xilinx/Vivado/2018.2/settings64.sh
vivado
Select a free HDL description of implementation of a vga module to a temporary directory or to your project directory. Our other module will be implmented using Verilog, but we can integrate Verilog and VHDL modules together in the schematic if desired. Here are examples of the type of vga modules for which you are looking. Make sure to respect any restrictions the authors place on copyrighted code that you use.
Download the code to a src directory
xxxxxxxxxx
mkdir ~/CMPE415/homeworks/hw1/src
cd ~/CMPE415/homeworks/hw1/src
wget http://web.mit.edu/6.111/www/f2005/code/jtag2mem_6111/vga_sync.v
Modify code to work with a 100-MHz clock change the 1-bit counter to a 2-bit counter
xxxxxxxxxx
// pixel clock: 25Mhz = 40ns (clk/2)
reg pcount; // used to generate pixel clock
wire en = (pcount == 0);
always @ (posedge clk) pcount <= ~pcount;
assign pix_clk = en;
becomes
xxxxxxxxxx
// pixel clock: 25Mhz = 40ns (clk/4)
reg [1:0] pcount; // used to generate pixel clock
wire en = (pcount == 0);
always @ (posedge clk) pcount <= pcount + 1 ;
assign pix_clk = en;
Add the source to the project using File-> Add Sources...
We will use the second option:
Click Add Files
navigate to src dir (e.g. /home/robucci/CMPE415/homeworks/hw1/src) and select the vga_sync.v file
You now have a new Design Source listed
We will now create a second source file.
Add a source as before, but this time select Create File
You should now have a shell created with port definitions. Double click the file to edit it and make the modifications below
Set the reg, green, and blue outputs as reg. Implementing registers avoids glitching (not that it is critical here). change
xxxxxxxxxx
output red,
output green,
output blue,
to
xxxxxxxxxx
output reg red,
output reg green,
output reg blue,
Add the following module code which takes the coodinates as inputs and outputs the color:
xxxxxxxxxx
parameter WIDTH = 20;
parameter HIEGHT = 100;
parameter X_LEFT = 320;
parameter Y_BOTTOM = 240;
//addinal intermediate logic signal wires
wire flag_on_rect; //high only when over rectangle
wire[9:0] x,y; //traditional cartesean coordinates, (left, bottom)=(0,0)
//combinatorial logic to calculate x,y coordinate system
assign x = pos_h;
assign y = 480 - pos_v;
//combinatorial logic to decide if present pixel is over a desired rectange region
assign flag_on_rect = x >= (X_LEFT) &&
x < (X_LEFT + WIDTH) &&
y >= (Y_BOTTOM) &&
y < (Y_BOTTOM + HIEGHT);
//combinatorial logic and registers (seqential logic) that load on rising clock edge
always @(posedge clk) begin
red <= flag_on_rect &~blank;
green <= ~flag_on_rect &~blank;
blue <= flag_on_rect &~blank;
end
The board that we are using can be considered as a reference board for learning to use the type of FPGA from Xilinx. Usually such boards come with a reference manual and what is called a constraint file that describes where pins are connected on the FPGA and the frequency the input clock generated on the board.
The provided file from one of these locations:
Place the file in your src directory
Uncomment the following lines set_property lines in the file:
xxxxxxxxxx
## Clock signal
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK100MHZ}];
xxxxxxxxxx
##VGA Connector
set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { VGA_R[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]
set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { VGA_G[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]
set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[1] }]; #IO_L4N_T0_35 Sch=vga_b[1]
set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { VGA_B[3] }]; #IO_L4P_T0_35 Sch=vga_b[3]
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { VGA_HS }]; #IO_L4P_T0_15 Sch=vga_hs
set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { VGA_VS }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs
Add the constraints file from the src directory.
You can note that the vga_r,vga_g, and vga_b are 4 bits each, but our vga_rectangle reg,green, and blue outputs are 1-bit.
Before we connect modules and FPGA pins, lets create some "glue logic" that expands a 1-bit to 4-bit
Create another module called bit_replicator_4x (be sure to store it in the src directory) with a 1-bit input "dIn" and a 4-bit output dOut. Add one line of code to the module:
xxxxxxxxxx
assign dOut = {4{dIn}};
We now want to create a top level design with modules connected using the following I/O names at the top level CLK100MHZ, VGA_R,VGA_G,VGA_B so that they match the provided constraints file and thus what you would find in the board documentation.
Two options are to create a Verilog file directly, and the second it to use a schematic tool to draw the design then generate the top level Verilog for it. We'll do the latter since it effectively shows both concepts.
We'll add a block design using Create Block Design
We'll choose a name "top" for the design and place it in the src directory
There is now a top.pd in your sources and a schematic waiting to be draw on the right:
To add your modules, and pins/ports use the right click menu within the Diagram area:
First add the vga_sync, then the vga_rectangle, then three of the bit_replicator_4x (can also use copy and paste get three)
block diagram design
Pins/port can be added using the same menu. Create
For VGA_G and VGA_B I copy&paste VGA_R then change the name using the property box (modules not show in this screenshot):
Here is a final schematic:
You can validate the design using the checkbox:
To make actually create our top level design, Vivado seems to requires a Verilog file, so right click the top.bd and select Create HDL Wrapper
I WOULD HAVE asked you to right-click the top_wrapper and select Set as Top, but if you wait a moment Vivado figures this out and moves the top indicator icon (green box above two gray boxes).
You can now click Generate Bitstream on the left, found right under Program and Debug
Use the defaults and ok-click through the next dialog.
You'll note progress/status/messaage in the upper-right corner of the Vivado window.
“Synthesize” and “Implement Design” are run automatically as needed.
This is what you are hoping for:
You can select Open Hardware Manger or access it from the left panel.
Proceed and then click the auto connect icon as show in the image:
Right Click the xc7z100t_0 and select Program Device:
OK-click through the dialogs (the correct .bit progamming file should be found automaticallly) and see if the magic happens. You should be able to connect a VGA monitor and see a Magenta rectangle on a Green Background.
Connect a VGA cable to the starter board and a monitor. You should see a magenta/purple rectange on a blue background.
Modify the design to have the ability to change the color of the rectangle based on switch positions.