Mohammad Hosseinabady
Published © MIT

A 0-9 Up/Down Counter in HLS

This project demonstrates the capability of high-level synthesis in describing digital systems by implementing a 0-9 Up/Down counter.

BeginnerFull instructions provided1 hour1,130
A 0-9 Up/Down Counter in HLS

Things used in this project

Hardware components

Basys 3
Digilent Basys 3
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1

Software apps and online services

Vivado Design Suite HLx Editions
AMD Vivado Design Suite HLx Editions

Story

Read more

Code

counter.h

C/C++
/************************************************
Copyright (c) 2020, Mohammad Hosseinabady
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Copyright (c) 2020, Mohammad Hosseinabady.
************************************************/
#ifndef __COUNTER_H__
#define __COUNTER_H__

#include <ap_int.h>


typedef ap_uint<8> uint8;
typedef ap_uint<5> uint5;
typedef ap_uint<4> uint4;
typedef ap_uint<2> uint2;
typedef ap_uint<1> uint1;

const uint8 seven_segment_code[10] = {
		0b11000000,
		0b11111001,
		0b10100100,
		0b10110000,
		0b10011001,
		0b10010010,
		0b10000010,
		0b11111000,
		0b10000000,
		0b10010000
};

#endif //__COUNTER_H__

counter.cpp

C/C++
/************************************************
Copyright (c) 2020, Mohammad Hosseinabady
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Copyright (c) 2020, Mohammad Hosseinabady.
************************************************/
#include "counter.h"



void counter(
		uint4 init_value,
		uint1 init_counter,
		uint2 push_buttons,
		uint4 &leds,
		uint8 &seven_segments_data,
		uint4 &seven_segments_enable) {

#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE ap_none port=init_value
#pragma HLS INTERFACE ap_none port=init_counter
#pragma HLS INTERFACE ap_none port=push_buttons
#pragma HLS INTERFACE ap_none port=leds
#pragma HLS INTERFACE ap_none port=seven_segments_data
#pragma HLS INTERFACE ap_none port=seven_segments_enable



	uint1 up_count   = push_buttons[0];
	uint1 down_count = push_buttons[1];
	static int up_pressed   = 0;
	static int down_pressed = 0;

	static uint4 number = 0;

	leds = init_value;

	seven_segments_enable = 0b1110;

	if (init_counter ==1) {
		number = init_value;
	}

	if (up_count == 0b1 && up_pressed == 0) {
		number++;
		if (number == 10)
			number = 0;
		up_pressed = 1000;
	}

	if (up_count == 0b0 &&  up_pressed > 0) {
		up_pressed--;
	}

	if (down_count == 0b1 && down_pressed == 0) {
		number--;
		if (number == 15)
			number = 9;
		down_pressed = 1000;
	}

	if (down_count == 0b0 && down_pressed > 0) {
		down_pressed--;
	}

	seven_segments_data = seven_segment_code[number];


}

counter-tb.h

C/C++
/************************************************
Copyright (c) 2020, Mohammad Hosseinabady
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Copyright (c) 2020, Mohammad Hosseinabady.
************************************************/
#ifndef __COUNTER_TB_H__
#define __COUNTER_TB_H__


#include "counter.h"

void counter(
		uint4 init_value,
		uint1 init_counter,
		uint2 push_buttons,
		uint4 &leds,
		uint8 &seven_segments_data,
		uint4 &seven_segments_enable);
#endif // __COUNTER_TB_H__

counter-tb.cpp

C/C++
/************************************************
Copyright (c) 2020, Mohammad Hosseinabady
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Copyright (c) 2020, Mohammad Hosseinabady.
************************************************/
#include "counter-tb.h"

void counter(
		uint5 push_buttons,
		uint8 &seven_segments_data,
		uint4 &seven_segments_enable);




int main() {

	int status = 0;
	uint2 push_buttons;
	uint8 seven_segments_data_hw;
	uint4 seven_segments_enable_hw;
	uint4 leds_hw;
	uint1 init_counter;
	uint4 init_value;


	uint4 leds_sw;
	uint8 seven_segments_data_sw;
	uint4 seven_segments_enable_sw;
	unsigned int software_counter=0;

	unsigned int button_pressed = 0;
	push_buttons = 0b10;

	for (int i = 0; (i < 10) && (status == 0) ; i++) {
		init_value = (uint4) i;

		for (int j = 0; (j < 2000) && (status == 0); j++) {
			if (j == 0) {
				init_counter = 1;
				software_counter = init_value;
			} else {
				init_counter = 0;
			}
			bool r = rand() % 2;
			if (button_pressed == 0) {
				button_pressed = 1000;
				if (r) {
					push_buttons = 0b01;
					if (software_counter == 9)
						software_counter = 0;
					else
						software_counter++;
				} else {
					push_buttons = 0b10;
					if (software_counter == 0)
						software_counter = 9;
					else
						software_counter--;
				}
			} else {
				button_pressed--;
				push_buttons = 0b00;
			}
			software_counter=software_counter%10;
			counter(init_value, init_counter, push_buttons, leds_hw, seven_segments_data_hw, seven_segments_enable_hw);

			seven_segments_data_sw   = seven_segment_code[software_counter];
			seven_segments_enable_sw = 0b1110;
			leds_sw                  =  init_value;

			if (    (seven_segments_data_hw != seven_segments_data_sw)
				 || (seven_segments_enable_hw != seven_segments_enable_sw)
				 || (leds_hw != leds_sw)
				)
			{
				status = 1;
				std::cout << " Error at "
						  << " software_counter = "
						  << software_counter
						  << " seven_segments_data_hw = " << seven_segments_data_hw.to_string()
						  << " seven_segments_data_sw = " << seven_segments_data_sw.to_string()
						  << " seven_segments_enable_hw = " << seven_segments_enable_hw.to_string()
						  << " seven_segments_enable_sw = " << seven_segments_enable_sw.to_string()
						  << " leds_hw = " << leds_hw.to_string()
						  << " leds_sw = " << leds_sw.to_string()
						  << std::endl;

			}
		}
	}



	if (status == 0) {
		std::cout << "Test Passed!" << std::endl;
	} else {
		std::cout << "Test Failed!" << std::endl;
	}



	return status;
}

counter.xdc

Tcl
## Switches
set_property PACKAGE_PIN V17 [get_ports {init_value[0]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {init_value[0]}]
set_property PACKAGE_PIN V16 [get_ports {init_value[1]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {init_value[1]}]
set_property PACKAGE_PIN W16 [get_ports {init_value[2]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {init_value[2]}]
set_property PACKAGE_PIN W17 [get_ports {init_value[3]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {init_value[3]}]


# LEDs
set_property PACKAGE_PIN U16 [get_ports {leds[0]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {leds[0]}]
set_property PACKAGE_PIN E19 [get_ports {leds[1]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {leds[1]}]
set_property PACKAGE_PIN U19 [get_ports {leds[2]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {leds[2]}]
set_property PACKAGE_PIN V19 [get_ports {leds[3]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {leds[3]}]


#7 segment display
set_property PACKAGE_PIN W7 [get_ports {seven_segments_data[0]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[0]}]
set_property PACKAGE_PIN W6 [get_ports {seven_segments_data[1]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[1]}]
set_property PACKAGE_PIN U8 [get_ports {seven_segments_data[2]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[2]}]
set_property PACKAGE_PIN V8 [get_ports {seven_segments_data[3]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[3]}]
set_property PACKAGE_PIN U5 [get_ports {seven_segments_data[4]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[4]}]
set_property PACKAGE_PIN V5 [get_ports {seven_segments_data[5]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[5]}]
set_property PACKAGE_PIN U7 [get_ports {seven_segments_data[6]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_data[6]}]

set_property PACKAGE_PIN V7 [get_ports seven_segments_data[7]]
	set_property IOSTANDARD LVCMOS33 [get_ports seven_segments_data[7]]

set_property PACKAGE_PIN U2 [get_ports {seven_segments_enable[0]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_enable[0]}]
set_property PACKAGE_PIN U4 [get_ports {seven_segments_enable[1]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_enable[1]}]
set_property PACKAGE_PIN V4 [get_ports {seven_segments_enable[2]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_enable[2]}]
set_property PACKAGE_PIN W4 [get_ports {seven_segments_enable[3]}]
	set_property IOSTANDARD LVCMOS33 [get_ports {seven_segments_enable[3]}]


#Buttons
set_property PACKAGE_PIN T18 [get_ports push_buttons[0]]
	set_property IOSTANDARD LVCMOS33 [get_ports push_buttons[0]]
set_property PACKAGE_PIN W19 [get_ports init_counter[0]]
	set_property IOSTANDARD LVCMOS33 [get_ports init_counter[0]]
set_property PACKAGE_PIN U17 [get_ports push_buttons[1]]
	set_property IOSTANDARD LVCMOS33 [get_ports push_buttons[1]]
	

Github

https://github.com/highlevelsynthesis/0-9-HLSCounter

Credits

Mohammad Hosseinabady

Mohammad Hosseinabady

14 projects • 94 followers
Mohammad Hosseinabady has a PhD degree in Computer and Electronics Engineering. He is an expert in High-Level Synthesis for FPGAs.

Comments