2020年3月4日 星期三

Verilog - Blinking a LED (DE2-115 GPIO)


Electronics - Verilog - Blinking a LED

Blinking a LED, a basic step.
But without this first step, there won't be a second.
And without second, no third and so on.
This simple tutorial will explain basics in order to program a blinking system.
Thus this timer example in Verilog could be seen as an Hello World exercise.
Let's get started.

Explanation

This tutorial has been made with the Altera DE1 board.
In Verilog, every program starts by a module.
This module will declare ports as:
  • input;
  • output;
  • inout.
A clock is an input because the pin where the clock is connected has to receive data from this clock.
An output will send data from the program to the pin.
So it's normal to set a LED as an output.
Our board has four green LEDs.
For our example we're going to use only two of them.
LEDG[1] will be always lit and the LEDG[0] will blink.
The reg element is there to hold a value.
1'b means that it'll be only 1 binary digit in this reg element.
So we declare three reg elements, one for a data holding a value of 1 in binary, the second to create a counter and the third to have a state.
Of course this state will change during the process.
Indeed, in the always@ block, we tell the process that for each clock's edge, the counter will be incremented by 1.
For the first code, called Quick blinking, we also tell the process that the state value will change  everytime the counter reach 2^20.
Why 2^20?
Because in binary this value is: 100000000000000000000.
We've twenty zeros, so we've 2^20 in binary.
In a decimal base it will be 1,048,576.
Our clock is at 50 MHz, meaning fifty million oscillations per second (it's huge, yes).
If we would like to know how long the LEDG[0] will stay high (switched on) or low (switched off) we've to do:
1,048,576 / 50,000,000 = 0.02097152
So approximately 0.02 second.
This time represents the moment when the LED is high (1) or when it's low (0).
So to retrieve the period (a cycle) we've to multiply this result by 2.
Then:
 0.02097152* 2 = 0.04194304
Approximately 0.04 second.
Now to know how many times the LEDG[0] will blink per second, we've just to do:
1 / 0.04194304 = 23.8418579102
So approximately 24 times per second, that is 24 Hz.
This frequency is a bit too quick.
Let's reduce it with the second code, called Slow blinking.
For that we've to change the counter-27th's bit (so 2^26).
Same as earlier:
2^26 = 67,108,864
Consequently:
67,108,864 / 50,000,000 = 1.34217728
And:
1.34217728 * 2 = 2.68435456
Our period is approximately 2.7.
1 / 2.68435456 = 0.37252902984.
Then the frequency is approximately 0.37 Hz.
And if you check the LED after sending the HDL on the board, you should see the LEDG[0] blinking once every 1.3 second (from low to high or high to low) and 2.7 seconds for a complete cycle (from low to low or high to high).

Code

Quick blinking

// Quick blinking a LED

/* module */
module blinking (

    input CLOCK_50,
    output [1:0] LEDG
    
);

    /* reg */
    reg data1 = 1'b1;
    reg [32:0] counter;
    reg state;
    
    /* assign */
    assign LEDG[0] = state;
    assign LEDG[1] = data1;
    
    /* always */
    always @ (posedge CLOCK_50) begin
        counter <= counter + 1;
        state <= counter[20]; // <------ data to change
    end

endmodule

Slow blinking

// Slow blinking a LED

/* module */
module blinking (

    input CLOCK_50,
    output [1:0] LEDG
    
);

    /* reg */
    reg data1 = 1'b1;
    reg [32:0] counter;
    reg state;
    
    /* assign */
    assign LEDG[0] = state;
    assign LEDG[1] = data1;
    
    /* always */
    always @ (posedge CLOCK_50) begin
        counter <= counter + 1;
        state <= counter[26]; // <------ data to change
    end

endmodule

Explanation

On the DE1 board, there are many GPIOs.
What is a GPIO? --> GPIO stands for General Purpose Input Output.
It's a group of pins that you can set to input or output individually.
It means that when a pin is set to ouput and when you send a 0 or a 1 on it, you can get this value outside the board.
And when it's input, you get data from outside.
In this tutorial we are going to use output direction.
On the DE1 board, there are 2 GPIOs:
  • GPIO_0
  • GPIO_1
As you can see from the video, there are two green LEDs plugged to the breadboard (on the right).
Each green LED is paired with a 150 ohm resistor.
The black wire is the GND that I've taken from GPIO_0[11] and the red wire is the VCC (+3V) taken from GPIO_0[28].
This first green LED is just here to say there is a current through the breadboard.
Then I've taken a green wire to connect the + of the second LED to the GPIO_1[0].
It could be a bit difficult to understand that, especially because on the DE1_Schematics (that you can find easily on Internet) the first pin starts from 1 and not 0.
Furthermore we use CLOCK_24[1] instead of the famous CLOCK_50.

Code

// module blink_led_gpio

module blink_led_gpio(

    input wire [1:0] CLOCK_24,
    output wire [35:0] GPIO_1
    
);

    // reg
    reg [32:0] counter;
    reg turn;
    
    // assign
    assign GPIO_1[0] = turn;
    
    // always
    always @(posedge CLOCK_24[1]) begin
        counter <= counter + 1;
        if (counter[25]) begin
            turn <= 1'b1;            // LED turned on
        end else begin
            turn <= 1'b0;            // LED turned off
        end
    end
    
endmodule
//需 Import  pin assignments  DE2_115_pin_assignments
// module blink_led_gpio

module GPIO_LED(SW, LEDR, LEDG , CLOCK_50 ,KEY ,HEX0 ,HEX1 ,HEX2,HEX3,HEX4 ,HEX5 ,HEX6,HEX7, GPIO );
 
 input  [17:0] SW;   // toggle switches
 input  [7:0] KEY;       // Push bottom
 input  CLOCK_50;   //Clock 27MHz , 50Mhz

 output [17:0] LEDR;   // red  LEDS 
 output [8:0] LEDG;   // green LEDs
 output [6:0] HEX0,HEX1,HEX2,HEX3; //7-segment display
 output [6:0] HEX4,HEX5,HEX6,HEX7; //7-segment display
 inout  [35:0] GPIO;
 
 assign HEX0=7'b111_1111;
 assign HEX1=7'b111_1111;
 assign HEX2=7'b111_1111;
 assign HEX3=7'b111_1111; 
 assign HEX4=7'b111_1111;
 assign HEX5=7'b111_1111;
 assign HEX6=7'b111_1111;
 assign HEX7=7'b111_1111;

    // reg
    reg [32:0] counter;
    reg turn;
    
    // assign
    assign GPIO[0] = turn;
    assign LEDR[0] = GPIO[11];
    
    // always
    always @(posedge CLOCK_50) begin
        counter <= counter + 1;
        if (counter[26]) begin
            turn <= 1'b1;            // LED turned on
        end else begin
            turn <= 1'b0;            // LED turned off
        end
    end
 
endmodule



沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...