Actions

FPGAWorkshop17Notes: Difference between revisions

From HacDC Wiki

No edit summary
Line 1: Line 1:
----
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
----
=[http://osobageqys.co.cc Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page]=
----
=[http://osobageqys.co.cc CLICK HERE]=
----
</div>
== PicoBlaze Flow / Tutorial ==
== PicoBlaze Flow / Tutorial ==


Line 66: Line 74:
This constraints file can be used with the design examples covered in this tutorial.
This constraints file can be used with the design examples covered in this tutorial.


<pre>
&lt;pre>
#
#
# UCF For Picoblaze Examples
# UCF For Picoblaze Examples
Line 81: Line 89:
# Require only 3.5mA.
# Require only 3.5mA.
#
#
NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED&lt;0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED&lt;1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED&lt;2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "LED&lt;3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led&lt;4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led&lt;5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<6>" LOC = "E9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led&lt;6>" LOC = "E9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<7>" LOC = "F9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led&lt;7>" LOC = "F9"  | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;


# Simple switches
# Simple switches
Line 96: Line 104:
#  sw1
#  sw1
NET "SW1" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP;
NET "SW1" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP;
</pre>
&lt;/pre>


=== picoblaze_example1.v ===
=== picoblaze_example1.v ===


<pre>  
&lt;pre>  
module picoblaze_example1(
module picoblaze_example1(
     input FPGA_RESET,
     input FPGA_RESET,
Line 143: Line 151:
         always @(posedge clock) begin
         always @(posedge clock) begin
                 if(write_strobe) begin
                 if(write_strobe) begin
                         userbit <= out_port;
                         userbit &lt;= out_port;
                 end
                 end
         end
         end
Line 150: Line 158:


endmodule
endmodule
</pre>  
&lt;/pre>  


=== example #1 source ===
=== example #1 source ===
<pre>
&lt;pre>
;
;
; simple example code, original
; simple example code, original
Line 171: Line 179:
XOR s9, 0xFF ;toggle register
XOR s9, 0xFF ;toggle register
JUMP drive_wave  
JUMP drive_wave  
</pre>
&lt;/pre>


== Example #2  ==
== Example #2  ==
Line 180: Line 188:


=== picoblaze_example2.psm source ===
=== picoblaze_example2.psm source ===
<pre>
&lt;pre>
;
;
; simple example code, shifting
; simple example code, shifting
; wait longer too
; wait longer too
;
;
start: LOAD s9, 0xA5 ; 10100101 ;  <---- THIS CHANGED
start: LOAD s9, 0xA5 ; 10100101 ;  &lt;---- THIS CHANGED
drive_wave: OUTPUT s9, 0x02 ; write s9 register to userbit
drive_wave: OUTPUT s9, 0x02 ; write s9 register to userbit
LOAD S2, 0x2F ; S2 initial value  <---- THIS CHANGED
LOAD S2, 0x2F ; S2 initial value  &lt;---- THIS CHANGED
loop2: LOAD S1, 0xFF ; S1 initial value
loop2: LOAD S1, 0xFF ; S1 initial value
loop1: LOAD s0, 0xFF ; S0 initial value
loop1: LOAD s0, 0xFF ; S0 initial value
Line 197: Line 205:
JUMP NZ, loop2
JUMP NZ, loop2
;
;
RL s9 ; shift left register ;  <---- THIS CHANGED
RL s9 ; shift left register ;  &lt;---- THIS CHANGED
JUMP drive_wave
JUMP drive_wave
</pre>
&lt;/pre>


== Example #3  ==
== Example #3  ==
Line 208: Line 216:


=== picoblaze_example3.v source ===
=== picoblaze_example3.v source ===
<pre>
&lt;pre>
module picoblaze_example3(
module picoblaze_example3(
     input FPGA_RESET,
     input FPGA_RESET,
Line 253: Line 261:
         always @(posedge clock)
         always @(posedge clock)
                 if(write_strobe)
                 if(write_strobe)
                         userbit <= out_port;
                         userbit &lt;= out_port;
            
            


Line 263: Line 271:
         always @(posedge clock)
         always @(posedge clock)
                 if(read_strobe)
                 if(read_strobe)
                         in_port <= switches;
                         in_port &lt;= switches;
                 else
                 else
                         in_port <= 8'bX;         
                         in_port &lt;= 8'bX;         


         assign LED = userbit;
         assign LED = userbit;
Line 271: Line 279:


endmodule
endmodule
</pre>
&lt;/pre>


=== picoblaze_example3.psm ===
=== picoblaze_example3.psm ===
<pre>
&lt;pre>
;
;
; simple example code, shifting and inverting
; simple example code, shifting and inverting
Line 306: Line 314:
invert_wave: XOR s9, 0xFF ;toggle register
invert_wave: XOR s9, 0xFF ;toggle register
JUMP drive_wave  
JUMP drive_wave  
</pre>
&lt;/pre>


However, that code is a bit hard to read!! It can be much easier to read mnemonics instead of hex value and register id's.  After getting the code above working, go ahead and add the following to the top of your picoblaze assembly source.  
However, that code is a bit hard to read!! It can be much easier to read mnemonics instead of hex value and register id's.  After getting the code above working, go ahead and add the following to the top of your picoblaze assembly source.  
<pre>
&lt;pre>
;
;
; Make it human readable with mnemonics!
; Make it human readable with mnemonics!
Line 326: Line 334:
CONSTANT BITMASK, 0x01
CONSTANT BITMASK, 0x01
;
;
</pre>
&lt;/pre>


After adding this section to your code, go through and replace the following items
After adding this section to your code, go through and replace the following items
Line 334: Line 342:
After replacing the constants, you're code should look like this
After replacing the constants, you're code should look like this


<pre>
&lt;pre>
start: LOAD WAVE_VAR, INITIAL_WAVE ;
start: LOAD WAVE_VAR, INITIAL_WAVE ;
drive_wave: OUTPUT WAVE_VAR, 0x02 ; write s9 register to userbit
drive_wave: OUTPUT WAVE_VAR, 0x02 ; write s9 register to userbit
Line 358: Line 366:
invert_wave: XOR WAVE_VAR, 0xFF ;toggle register
invert_wave: XOR WAVE_VAR, 0xFF ;toggle register
JUMP drive_wave  
JUMP drive_wave  
</pre>
&lt;/pre>


== Run the simulator ==
== Run the simulator ==
Line 365: Line 373:


== Acknowledgements / References ==
== Acknowledgements / References ==
This was based on a simple example found here  http://forums.xilinx.com/xlnx/board/message?board.id=PicoBlaze&thread.id=780 <br>
This was based on a simple example found here  http://forums.xilinx.com/xlnx/board/message?board.id=PicoBlaze&amp;thread.id=780 &lt;br>
The Picoblaze download can be found here http://www.xilinx.com/products/ipcenter/picoblaze-S3-V2-Pro.htm <br>
The Picoblaze download can be found here http://www.xilinx.com/products/ipcenter/picoblaze-S3-V2-Pro.htm &lt;br>
OpenPicIDE is available here http://openpicide.org <br>
OpenPicIDE is available here http://openpicide.org &lt;br>


[[Category:FPGAWorkshop]]
[[Category:FPGAWorkshop]]

Revision as of 02:42, 24 November 2010


PicoBlaze Flow / Tutorial

THIS SET OF INSTRUCTIONS ASSUMES THE READER IS FAMILIAR WITH THE ISE SUITE FLOW FOR CREATING, IMPLEMENTING AND PROGRAMING PROJECTS.

Overview of Picoblaze / ISE Development flow

The PicoBlaze development flow is different from the FPGA flow we've seen so far. We have to use a new tool, a PicoBlaze assembler, in conjunction with the ISE tool set.

Picoblaze flow.png

I reccomend placing a folder named 'asssembly' or something else memorable in the root of your desired ISE project. This will keep an entire project togetheer in a single directory. You'll want to copy the ROM_form.vhd file from the picoblaze processor distribution to a convenient place, such as ./assembly directory or your project directory. We'll need to have a copy of this to use later.

The new tool we'll be working with today is openpicide. It is a project management IDE, Syntax check, program assembler and device simulator. It is opensource project, based on the QT framework. We'll be using it to generate the program ROM as a VHDL block ram file, which will be used with our design. The structure of our example project will look like the following:

  1. top_level.v
    1. embedded_kcpsm3.v
      1. kcpsm3.v
      2. prog_rom.vhd - This is the file generated by the assembler.
  2. project_constraints.ucf

In general, a picoblaze design would look like this

  1. top_level.v
    1. embedded_kcpsm3.v
      1. kcpsm3.v
        1. prog_rom.vhd - This is the file generated by the assembler.
    2. periperal1.v
    3. periperal2.v
      1. sub_module1.v
      2. ....
    4. other logic as needed
  2. project_constraints.ucf

Example #1

Picoblaze simple example / toolchain tutorial

To begin, make sure you've got Xilinx ISE and OpenpicIDE installed. You can obtain openpicIDE here http://openpicide.org/ You'll also need to get the picoblaze download package.

First, we'll create the ISE project. Create a new project called picoblaze_example1 in your projects directory. Add copies of the following files from the picoblaze download package.

  • embedded_kcpsm3.v
  • kcpsm3.v

Then create 2 new source files

  • constraints.ucf
  • picoblaze_example1.v.

Copy and paste the contents of these files from the wiki [see below]. You should note that your missing a file, prog_rom, which is in the embedded_kcpsm3 module. Do not attempt to implement the design - it will not work until we generate the program ROM.

When openpicide opens, you'll want to create a project. You should save the project file in your 'assembly' folder as "picoblaze_example1". Under the settings for the project, you'll need to do the following:

  1. Set the processor to Xilinx picoblaze
  2. Under the VHDL tab, set the entity name to "prog_rom"
  3. Set the vhdl source file to the ROM_form.vhd file we copied earlier.
  4. You can leave the rest of the settings to their default values.

You'll then need to create a new file - use the new file button in the upper left corner, or go to File -> New. Copy and paste the 1st example source file from the wiki. Using the Picoblaze Menu Run a syntax check on the code to make sure it is correct, and then generate a VHDL memory file from the code. Save the file as "prog_rom_example1.vhd" in your assembly section. You can now move back to ISE.

note: the picoblaze assembly files and the openpicide project file need to be in the same directory

Now, add the program file "prog_rom_example1.vhd" to your project, using "Add Copy of Source". You'll notice that the prog_rom module is no longer missing. You now need to comment out line 29, defining the constraint for SW1, from the UCF file. After that is commented out, you can implement the design. After programming the board, you should now see the LED's flipping on and off; if so, you have a working Picoblaze toolchain.

constraints.ucf

This constraints file can be used with the design examples covered in this tutorial.

<pre>

  1. UCF For Picoblaze Examples
  2. Period constraint for 50MHz operation, assume a 50% duty cycle, +/- 10%

NET "CLK_50MHZ" PERIOD = 20.0ns HIGH 40%;

  1. soldered 50MHz Clock.

NET "CLK_50MHZ" LOC = "C9" | IOSTANDARD = LVTTL;

  1. Simple LEDs
  2. Require only 3.5mA.

NET "LED<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "LED<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "LED<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "LED<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "led<4>" LOC = "C11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "led<5>" LOC = "D11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "led<6>" LOC = "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4; NET "led<7>" LOC = "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;

  1. Simple switches
  2. Pull UP resistors used to stop floating condition during switching.
  3. sw0

NET "FPGA_RESET" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP;

  1. sw1

NET "SW1" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP; </pre>

picoblaze_example1.v

<pre> module picoblaze_example1(

   input FPGA_RESET,
   input CLK_50MHZ,
   output [7:0] LED
   );
  wire clock = CLK_50MHZ;
       // reset is active high.
       // if no reset signal input
       // then tie reset to zero here.
       wire             reset = FPGA_RESET;
       wire [7:0]    port_id;
       wire            write_strobe;
       wire             read_strobe;
       wire [7:0]    out_port;
       wire [7:0]    in_port=0;
       wire            interrupt=0;
       wire            interrupt_ack;

       embedded_kcpsm3 EMBEDDED(
               .port_id(port_id),
               .write_strobe(write_strobe),
               .read_strobe(read_strobe),
               .out_port(out_port),
               .in_port(in_port),
               .interrupt(interrupt),
               .interrupt_ack(interrupt_ack),
               .reset(reset),
               .clk(clock)
       );
       // only one bit written to by picoblaze, the LED.
       // therefore don't need to decode port_id.
       // if write_strobe asserts, grab out_port[0] and
       // hold it in userbit.
       reg [7:0] userbit = 0;
       always @(posedge clock) begin
               if(write_strobe) begin
                       userbit <= out_port;
               end
       end
         
       assign LED = userbit;

endmodule </pre>

example #1 source

<pre>

simple example code, original

start: LOAD s9, 0xAA drive_wave: OUTPUT s9, 0x02 ; write s9 register to userbit LOAD S2, 0x0F ; S2 initial value loop2: LOAD S1, 0xFF ; S1 initial value loop1: LOAD s0, 0xFF ; S0 initial value loop0: SUB s0, 0x01 JUMP NZ, loop0 SUB s1, 0x01 JUMP NZ, loop1 SUB s2, 0x01 JUMP NZ, loop2

XOR s9, 0xFF ;toggle register JUMP drive_wave </pre>

Example #2

Expanding on the example

Create a new picoblaze project, in the assembly directory. Use the source from example #2 to create a new program rom file. You can name this program rom "prog_rom_example2.vhd". Copy this into your ISE project, and then remove the original prog_rom_example1.vhd from your project. Rebuild the project and reprogram your board. Your LEDs should be shifty now, instead of inverting!

picoblaze_example2.psm source

<pre>

simple example code, shifting
wait longer too

start: LOAD s9, 0xA5 ; 10100101 ; <---- THIS CHANGED drive_wave: OUTPUT s9, 0x02 ; write s9 register to userbit LOAD S2, 0x2F ; S2 initial value <---- THIS CHANGED loop2: LOAD S1, 0xFF ; S1 initial value loop1: LOAD s0, 0xFF ; S0 initial value loop0: SUB s0, 0x01 JUMP NZ, loop0 SUB s1, 0x01 JUMP NZ, loop1 SUB s2, 0x01 JUMP NZ, loop2

RL s9 ; shift left register ; <---- THIS CHANGED JUMP drive_wave </pre>

Example #3

Lets add some input

Lets read in a switch now! To do this, you can do one of two things. You can add a input port, and add the multiplexed input re g manually. I've already built this example, so you can create a new ISE project. Can call this project "picoblaze_example3". Follow the instructions from earlier in the tutorial, but use the following verilog source file. You'll also need to create a new OpenPicIDE project with the source used in the following example. Make sure that SW1 is not commented out in your UCF file.

picoblaze_example3.v source

<pre> module picoblaze_example3(

   input FPGA_RESET,
   input CLK_50MHZ,
   input SW1,
   output [7:0] LED
   );
  wire clock = CLK_50MHZ;
       // reset is active high.
       // if no reset signal input
       // then tie reset to zero here.
       wire             reset = FPGA_RESET;
       wire [7:0]    port_id;
       wire            write_strobe;
       wire             read_strobe;
       wire [7:0]    out_port;
       reg [7:0]    in_port;
       wire [7:0]   switches;
       wire            interrupt=0;
       wire            interrupt_ack;

       embedded_kcpsm3 EMBEDDED(
               .port_id(port_id),
               .write_strobe(write_strobe),
               .read_strobe(read_strobe),
               .out_port(out_port),
               .in_port(in_port),
               .interrupt(interrupt),
               .interrupt_ack(interrupt_ack),
               .reset(reset),
               .clk(clock)
       );
       // only one bit written to by picoblaze, the LED.
       // therefore don't need to decode port_id.
       // if write_strobe asserts, grab out_port[0] and
       // hold it in userbit.
       reg [7:0] userbit = 0;
       always @(posedge clock)
               if(write_strobe)
                       userbit <= out_port;
          
       // only one bit is read by picoblaze, the SW1.
       // therefore don't need to decode port_id.
       // if read_strobe asserts, grab swib out_port[0] and
       // hold it in userbit.
       always @(posedge clock)
               if(read_strobe)
                       in_port <= switches;
               else
                       in_port <= 8'bX;         
       assign LED = userbit;
       assign switches = {7'b0, SW1};

endmodule </pre>

picoblaze_example3.psm

<pre>

simple example code, shifting and inverting
wait longer too
read in a switch at each loop, if the switch is 1 then invert
the register instead of shifting it

start: LOAD s9, 0xA5 ; 10100101 drive_wave: OUTPUT s9, 0x02 ; write s9 register to userbit LOAD S2, 0x2F ; S2 initial value loop2: LOAD S1, 0xFF ; S1 initial value loop1: LOAD s0, 0xFF ; S0 initial value loop0: SUB s0, 0x01 JUMP NZ, loop0 SUB s1, 0x01 JUMP NZ, loop1 SUB s2, 0x01 JUMP NZ, loop2

Read the inport to s8

INPUT s8, 0x01

test bit 0, if 1, set carry flag

TEST s8, 0x01

if (s8[0] == 1) invert_wave else shift_wave

JUMP C, invert_wave

shift the wave and drive it

shift_wave: RL s9 ; shift left register JUMP drive_wave

invert the wave and drive it

invert_wave: XOR s9, 0xFF ;toggle register JUMP drive_wave </pre>

However, that code is a bit hard to read!! It can be much easier to read mnemonics instead of hex value and register id's. After getting the code above working, go ahead and add the following to the top of your picoblaze assembly source. <pre>

Make it human readable with mnemonics!

NAMEREG S0, I_VAR NAMEREG S1, J_VAR NAMEREG S2, K_VAR NAMEREG S9, WAVE_VAR NAMEREG S8, SCRATCH_VAR

CONSTANT INITIAL_I, 0xFF CONSTANT INITIAL_J, 0xFF CONSTANT INITIAL_K, 0x2F CONSTANT INITIAL_WAVE, 0xA5 ;10100101 CONSTANT BITMASK, 0x01

</pre>

After adding this section to your code, go through and replace the following items

  • Register references, sX, should be replaced with the variable names
  • Constants which are named should be replaced.

After replacing the constants, you're code should look like this

<pre> start: LOAD WAVE_VAR, INITIAL_WAVE ; drive_wave: OUTPUT WAVE_VAR, 0x02 ; write s9 register to userbit LOAD K_VAR, INITIAL_K ; S2 initial value loop2: LOAD J_VAR, INITIAL_J ; S1 initial value loop1: LOAD I_VAR, INITIAL_I ; S0 initial value loop0: SUB I_VAR, 0x01 JUMP NZ, loop0 SUB J_VAR, 0x01 JUMP NZ, loop1 SUB K_VAR, 0x01 JUMP NZ, loop2

Read the inport to s8

INPUT SCRATCH_VAR , 0x01

test bit 0, if 1, set carry flag

TEST SCRATCH_VAR , BITMASK

if (s8[0] == 1) invert_wave else shift_wave\

JUMP C, invert_wave

shift the wave and drive it

shift_wave: RL WAVE_VAR ; shift left register JUMP drive_wave

invert the wave and drive it

invert_wave: XOR WAVE_VAR, 0xFF ;toggle register JUMP drive_wave </pre>

Run the simulator

Now we have mnemonics entered into our code, we can easily tweak it. First, we can change the I_Var, J_Var, K_Var, to be smaller values, such as 0x0F. You can then step through the program, or just run it, in the OpenPicIDE simulator.

Acknowledgements / References

This was based on a simple example found here http://forums.xilinx.com/xlnx/board/message?board.id=PicoBlaze&thread.id=780 <br> The Picoblaze download can be found here http://www.xilinx.com/products/ipcenter/picoblaze-S3-V2-Pro.htm <br> OpenPicIDE is available here http://openpicide.org <br>