Skip to content

Example: Blink LEDs

Julian Kemmerer edited this page Aug 2, 2020 · 20 revisions

This is an in depth break down of an blinking LED example design to show the PipelineC tool flow.

This example is from a series of examples designed for the Arty Board.

Source

// Use the switches to control LED blink rate

#include "uintN_t.h"

// Each main function is a clock domain
// Only one clock in the design for now 'sys_clk' @ 100MHz
#pragma MAIN_MHZ sys_clk_main 100.0
#pragma PART "xc7a35ticsg324-1l" // xc7a35ticsg324-1l = Arty, xcvu9p-flgb2104-2-i = AWS F1

// Make structs that wrap up the inputs and outputs
typedef struct sys_clk_main_inputs_t
{
	// The switches
	uint4_t sw;
} sys_clk_main_inputs_t;
typedef struct sys_clk_main_outputs_t
{
	// The LEDs
	uint1_t led[4];
} sys_clk_main_outputs_t;

// Blinking means turn on LED for some amount of time, and then turn off
// How much time?
#define BLINK_CLK_CYCLES 10000000
// The switch value, ex. sw[3:0] = 0b1101 = 13
// multiplies the above constant to determine actual blink rate
// Ex. 10000000*13 = 130000000 cycles, 100MHz = 10ns per clock, 130000000 * 10ns = 1.3 sec

// We need to count up to whatever sw*BLINK_CLK_CYCLES equals
uint28_t counter; // Inits to zero
// And we need to remember if the LEDs are on or not - so we know what to do next
uint1_t leds_on;

// The sys_clk_main function
sys_clk_main_outputs_t sys_clk_main(sys_clk_main_inputs_t inputs)
{
    // Do what counters do, increment
    counter = counter + 1;

    // If the counter equals or greater then
    // time to toggle the led and reset counter
    if(counter >= (inputs.sw * BLINK_CLK_CYCLES))
    {
        leds_on = !leds_on;
        counter = 0;
    }

    // Drive output leds (all 4)
    sys_clk_main_outputs_t outputs;
    outputs.led[0] = leds_on;
    outputs.led[1] = leds_on;
    outputs.led[2] = leds_on;
    outputs.led[3] = leds_on;

    return outputs;
}

PipelineC Tool Output

Pipeline Map

The compiler produces a text representation of what operations occur at which point during the pipeline (i.e. how long each operation takes and when). Inputs flow from top to bottom. Functions listed on the same lines are occurring in parallel.

Synthesizing function: sys_clk_main
Pipeline Map:
0: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
1: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
2: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
3: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
4: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
5: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
6: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
7: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
8: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
9: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
10: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
11: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]', 'UNARY_OP_NOT[blink_c_l44_c20_f44b]']
12: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
13: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
14: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
15: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
16: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
17: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
18: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
19: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
20: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
21: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
22: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
23: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
24: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
25: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
26: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
27: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
28: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
29: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
30: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
31: ['BIN_OP_MULT[blink_c_l42_c20_ea96]', 'BIN_OP_PLUS[blink_c_l38_c15_6a92]']
32: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
33: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
34: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
35: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
36: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
37: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
38: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
39: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
40: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
41: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
42: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
43: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
44: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
45: ['BIN_OP_MULT[blink_c_l42_c20_ea96]']
46: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
47: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
48: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
49: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
50: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
51: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
52: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
53: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
54: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
55: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
56: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
57: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
58: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
59: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
60: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
61: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
62: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
63: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
64: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
65: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
66: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
67: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
68: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
69: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
70: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
71: ['BIN_OP_GTE[blink_c_l42_c8_03a9]']
72: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
73: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
74: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
75: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
76: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
77: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
78: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
79: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
80: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
81: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
82: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
83: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
84: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
85: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
86: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']
87: ['counter_MUX[blink_c_l42_c5_41ed]', 'leds_on_MUX[blink_c_l42_c5_41ed]']

VHDL wrapper for Vivado

-- Top level file connecting to PipelineC generated code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

-- PipelineC packages
use work.c_structs_pkg.all;

entity board is
  port (
    CLK100MHZ : in std_logic;
    sw : in std_logic_vector(3 downto 0);
    led : out std_logic_vector(3 downto 0)
  );
end board;

architecture arch of board is
  
-- Sync inputs to CLK100MHZ
signal sw_r, sw_rr : std_logic_vector(3 downto 0);
  
-- IO type conversion
signal sys_clk_main_inputs : sys_clk_main_inputs_t;
signal sys_clk_main_outputs : sys_clk_main_outputs_t;
  
begin

-- Sync inputs to CLK100MHZ
process(CLK100MHZ) begin
    if rising_edge(CLK100MHZ) then
        sw_r <= sw;
        sw_rr <= sw_r;
    end if;
end process;

-- IO type conversion
process(
    -- Inputs to module
    sw_rr, 
    -- Outputs from PipelineC
    sys_clk_main_outputs
) begin
    -- Input
    sys_clk_main_inputs.sw(0) <= sw_rr(0);
    sys_clk_main_inputs.sw(1) <= sw_rr(1);
    sys_clk_main_inputs.sw(2) <= sw_rr(2);
    sys_clk_main_inputs.sw(3) <= sw_rr(3);
    
    -- Outputs
    led(0) <= sys_clk_main_outputs.led(0)(0);
    led(1) <= sys_clk_main_outputs.led(1)(0);
    led(2) <= sys_clk_main_outputs.led(2)(0);
    led(3) <= sys_clk_main_outputs.led(3)(0);
end process;

-- The PipelineC generated entity
top_inst : entity work.top port map (
    clk_sys_clk_main => CLK100MHZ,
    sys_clk_main_inputs => sys_clk_main_inputs,
    sys_clk_main_return_output => sys_clk_main_outputs
);

end arch;
Clone this wiki locally