Jump to content
  • 0

CMOD A7 Programming Guidance


Benmo

Question

Hi, 

I have very little experience with programming FPGA's so recently purchased a CMOD A7 to teach myslef. I have followed the tutorial on LED Button  and it worked fine. What i would like to do next create a sketch that turns on the LED when a pin goes HIGH and then once I understand how to do this output a pin HIGH when another goes HIGH. 

Below is the file used for the LED when button is pressed.

Where can I go to learn how to do this? 

In the code below what does `timescale 1ns / 1ps do? 

 

`timescale 1ns / 1ps

module btn_led(
    input [1:0]btn,   // Button inputs
    output [1:0]led  // Led outputs
    );
    
    // Assign each btn to it's respective led
    assign led = btn;
    
endmodule

 

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

@Benmo,

I think I answered some of your question(s) here.

As for setting an LED on a button press ... I'm not quite certain what you wish to do.  Worse, buttons can "bounce", and so they aren't necessarily the greatest beginner project.  Are you sure you don't want to build a serial port next?  Maybe set an LED any time the serial port receives an 'L' character?  I'm also very partial to the Knight Rider LED project as a beginner's challenge.

Dan

Link to comment
Share on other sites

Hi @Benmo,

Another follow-up question I have is what sort of behavior you are looking for in your described situation. If you want an LED or a different pin to become an output high when a particular input (button or otherwise) is at a logic high state, then you your code is essentially done. The catch here is that when that input is becomes logic low the LED or other output will also become low. If you instead want to keep its state (press once, the output turns "on", press again, the output turns "off", repeat), that will become more difficult, especially with the button bounce that @D@n mentioned. The serial port option is a little easier to accomplish that functionality in that regard and in my opinion a little more satisfying. The short answer to your 'timescale question is that it mostly there for simulation purposes and to help keep Vivado from complaining.

Thanks,
JColvin

Link to comment
Share on other sites

Given the popularity of the question, maybe it helps to show a complete example.

There's a risk that it solves someone's very basic homework problem... if so, better spend some time with it to decipher my handwriting :)

Complete Vivado project:

https://drive.google.com/file/d/1Mi88WTpC7SWzoui3rn6o2FcVv0WOAaN7/view?usp=sharing

Verilog:

// === CMOD A7 demo ====
// buttons cycle LEDs forwards / backwards

// === require explicit "wire" ===
`default_nettype none
  
  module top(input wire CLK12, 
	     output wire [1:0] LED, 
	     output wire       RGB0_Red, 
	     output wire       RGB0_Green, 
	     output wire       RGB0_Blue, 
	     input wire [1:0]  BTN);
   
   // === import asynchronous signals ===
   // synchronizer avoids metastability issues (may be overkill in this example)
   (* ASYNC_REG = "TRUE" *)reg [1:0] 		      BTN_A = 2'd0;
   (* ASYNC_REG = "TRUE" *)reg [1:0] 		      BTN_B = 2'd0;
   always @(posedge CLK12) begin
      BTN_A <= BTN;
      BTN_B <= BTN_A;
   end
   
   // === debounce ===
   // sharing one counter for both buttons
   reg [19:0] 		      debounce = 20'd0;
   wire 		      buttonStrobe = (debounce == 20'd1); // debounce == 1 triggers button event
   reg [1:0] 		      lastBtn = 2'd0;      
   always @(posedge CLK12) begin
      lastBtn <= BTN_B;
      // count debounce down to zero
      debounce <= (debounce == 20'd0) ? (20'd0) : (debounce - 20'd1);
      // change of button state resets debounce (overrides above assignment)
      if (lastBtn != BTN_B)
	debounce <= 20'hFFFFF;      
   end

   // === FSM ===
   reg [5:0] ledOut = 6'd1;
   always @(posedge CLK12)
     if (buttonStrobe)
       case (lastBtn)
	 2'b01: ledOut <= {ledOut[0], ledOut[5:1]}; // shift forwards
	 2'b10: ledOut <= {ledOut[4:0], ledOut[5]}; // shift backwards       
       endcase
   
   // === access to DONE_LED via instantiated STARTUPE2 ===
   wire      DONE_LED;   
   STARTUPE2 iStartupE2(.USRCCLKO(1'b0), .USRCCLKTS(1'b0), .USRDONEO(DONE_LED), .USRDONETS(1'b0));
   
   // === map LEDs ===
   assign LED[0] = ledOut[0];
   assign LED[1] = ledOut[1];
   assign DONE_LED = ledOut[2];   
   assign RGB0_Red = ~ledOut[3];
   assign RGB0_Green = ~ledOut[4];
   assign RGB0_Blue = ~ledOut[5];
endmodule

Constraints file:

# Clock signal 12 MHz
set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS33} [get_ports CLK12]
create_clock -add -name sys_clk_pin -period 83.33 -waveform {0 41.66} [get_ports {CLK12}];

# LEDs
set_property -dict {PACKAGE_PIN A17 IOSTANDARD LVCMOS33} [get_ports {LED[0]}]
set_property -dict {PACKAGE_PIN C16 IOSTANDARD LVCMOS33} [get_ports {LED[1]}]

set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]

set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS33} [get_ports RGB0_Red]
set_property -dict {PACKAGE_PIN B16 IOSTANDARD LVCMOS33} [get_ports RGB0_Green]
set_property -dict {PACKAGE_PIN B17 IOSTANDARD LVCMOS33} [get_ports RGB0_Blue]

# Buttons
set_property -dict {PACKAGE_PIN A18 IOSTANDARD LVCMOS33} [get_ports {BTN[0]}]
set_property -dict {PACKAGE_PIN B18 IOSTANDARD LVCMOS33} [get_ports {BTN[1]}]

# set asynchronous outputs as don't-care
set_false_path -from [get_ports BTN]
set_false_path -to [get_ports LED]
set_false_path -to [get_ports RGB0_Red]
set_false_path -to [get_ports RGB0_Green]
set_false_path -to [get_ports RGB0_Blue]

Compile and upload to the CMOD A7 and it'll cycle the LEDs forwards when pressing the first button, and backwards when pressing the other button.

Features:

  • Asynchronous Button signals are brought in through a synchronizer (may be overkill here but it's mandatory for regular digital signals)
  • Debouncing via a counter, generates a buttonStrobe signal for the duration of one clock cycle
  • State machine shifts forwards on 01 button pattern, and backwards on 10. This is a playground for experiments, add your own logic here (my shift register example is compact but there is little "meat" to it)
  • LEDs are inverted as needed. The "DONE" LED is a special case, it needs an instantiated block to access the pin.

Happy FSM-ing :D

Link to comment
Share on other sites

On 3/6/2018 at 1:43 AM, Benmo said:

In the code below what does `timescale 1ns / 1ps do?

To add to @JColvin's comment beginners should be aware that VHDL and Verilog were not originally designed to do synthesis. To quote the Xilinx Synthesis and Simulation Design Guide:

VHDL and Verilog were not originally intended as inputs to synthesis. For this reason, synthesis tools do not support many hardware description and simulation constructs. In addition, synthesis tools may use different subsets of VHDL and Verilog. VHDL and Verilog semantics are well defined for design simulation. The synthesis tools must adhere to these semantics to ensure that designs simulate the same way before and after synthesis.

I've been doing field programmable logic device development long enough to remember when the only "HDL" text source languages were AHDL or WARP, before the days when vendors got the bright idea to co-opt VHDL and Verilog for synthesis. I decided to quote another source because usually when I mention this I get responses varying between blank stares and "well I know that's not true...".

I highly recommend getting comfortable with reading and understanding the reference material from the FPGA vendor who's tools and devices you are working with. Experienced developers might want to check out System C as an alternative.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...