-
Notifications
You must be signed in to change notification settings - Fork 56
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.
// 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;
}-- 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;