如何在HLS中描述数字时钟?

描述

绪论

该项目的目标是展示 HLS 在设计数字系统方面的能力。为此,本文展示如何在 HLS 中描述数字时钟。

时钟在 7 段数码管上显示小时、分钟和秒。

FPGA

它有两种操作模式:时钟和设置。时钟模式是标准模式,在此模式下,当前时间显示在数码管上。在设置模式下,可以使用按钮设置时间。

下图显示开发板上的时钟配置。

FPGA

如下图所示,该设计主要分为三个模块:秒时钟发生器、数字时钟引擎和显示驱动。

FPGA

下面的流水线循环用于实现秒时钟发生器。

 

bool delay(long long int n) {
#pragma HLS INLINE off
static bool dummy = 0;
for (long long int j = 0; j < n; j++) {
#pragma HLS pipeline
dummy = !dummy;
}
return dummy;
}
void one_second_clock_generator(bool &second) {
#pragma HLS INTERFACE ap_none port=second
#pragma HLS INTERFACE ap_ctrl_none port=return
static bool s = 0;
s=!s;
second = s;
delay(50000000L);
}

 

数字时钟引擎主要是跟踪小时、分钟和秒,并在收到来自秒时钟发生器模块的时钟节拍时更新它们。以下代码完成上诉功能。

 

void debounce(bool pulse, bool &out) {
#pragma HLS INLINE off
static bool out0 = 0;
static bool out1 = 0;
static bool out2 = 0;
static bool state = 0;
if (state == 0) {
out2 = out1;
out1 = out0;
out0 = pulse;
state = 1;
} else {
delay(2500000);
state = 0;
}
out = out0 & out1 & out2;
}
void set_time(
ap_uint<6>  &seconds,
ap_uint<6>  &minutes,
ap_uint<5>  &hours,
bool        set_second,
bool        set_minute,
bool        set_hour)
{
//--------------------------------------------------
static bool second_state = 0;
if (second_state == 0 && set_second == 1 ) {
seconds++;
if (seconds == 60) {
seconds = 0;
}
second_state = 1;
}
if (second_state == 1 && set_second == 0 ) {
second_state = 0;
}
//---------------------------------------------------
static bool minute_state = 0;
if (minute_state == 0 && set_minute == 1 ) {
minutes++;
if (minutes == 60) {
minutes = 0;
}
minute_state = 1;
}
if (minute_state == 1 && set_minute == 0 ) {
minute_state = 0;
}
//----------------------------------------------------
static bool hour_state = 0;
if (hour_state == 0 && set_hour == 1) {
hours++;
if (hours == 24) {
hours = 0;
}
hour_state = 1;
}
if (hour_state == 1 && set_hour == 0) {
hour_state = 0;
}
//----------------------------------------------------
}
void clock_ticking(
ap_uint<5> &hours,
ap_uint<6> &minutes,
ap_uint<6> &seconds)
{
seconds++;
if (seconds == 60) {
seconds = 0;
minutes++;
if (minutes == 60) {
minutes = 0;
hours++;
if (hours == 24)
hours = 0;
}
}
}
void digital_clock(
bool        set_time_sw,
bool       &set_time_led,
bool        set_second,
bool        set_minute,
bool        set_hour,
bool        one_second_delay,
ap_uint<6>  &seconds_out,
ap_uint<6>  &minutes_out,
ap_uint<5>  &hours_out
)
{
#pragma HLS INTERFACE ap_none port=set_time_sw
#pragma HLS INTERFACE ap_none port=set_time_led
#pragma HLS INTERFACE ap_none port=set_minute
#pragma HLS INTERFACE ap_none port=set_hour
#pragma HLS INTERFACE ap_none port=seconds_out
#pragma HLS INTERFACE ap_none port=minutes_out
#pragma HLS INTERFACE ap_none port=hours_out
#pragma HLS INTERFACE ap_ctrl_none port=return
static ap_uint<6> seconds = 0;
static ap_uint<6> minutes = 0;
static ap_uint<5> hours   = 0;
ap_uint<8> segment_data;
ap_uint<8> segment_enable;
static bool state_clock = 0;
bool        one_second = one_second_delay;
bool        set_time_flag = set_time_sw;
if (one_second==1&&set_time_flag==0&&state_clock==0) {
clock_ticking(hours, minutes, seconds);
state_clock = 1;
}
if (one_second==0&&set_time_flag==0&&state_clock==1) {
state_clock = 0;
}
if (set_time_flag == 1) {
bool set_minute_debounce;
bool set_hour_debounce;
bool set_second_debounce;
debounce (set_minute, set_minute_debounce);
debounce (set_hour, set_hour_debounce);
debounce (set_second, set_second_debounce);
set_time(seconds, minutes, hours, set_second_debounce, set_minute_debounce, set_hour_debounce);
}
seconds_out = seconds;
minutes_out = minutes;
hours_out   = hours;
set_time_led = set_time_sw;
}

 

最后一个 HLS 代码在 7 段数码管上显示当前时间。

 

#include 
const ap_uint<8> seven_segment_code[10] = {
0b11000000,
0b11111001,
0b10100100,
0b10110000,
0b10011001,
0b10010010,
0b10000010,
0b11111000,
0b10000000,
0b10010000
};
bool delay(long long int n) {
#pragma HLS INLINE off
static bool dummy = 0;
for (long long int j = 0; j < n; j++) {
#pragma HLS pipeline
dummy = !dummy;
}
return dummy;
}
void seven_segment_display(
ap_uint<5> hours,
ap_uint<6> minutes,
ap_uint<6> seconds,
ap_uint<8> &seven_segment_data,
ap_uint<8> &seven_segment_enable)
{
#pragma HLS INTERFACE ap_none port=hours
#pragma HLS INTERFACE ap_none port=minutes
#pragma HLS INTERFACE ap_none port=seconds
#pragma HLS INTERFACE ap_none port=seven_segment_data
#pragma HLS INTERFACE ap_none port=seven_segment_enable
#pragma HLS INTERFACE ap_ctrl_none port=return
ap_uint<4> second_digit_1 = seconds%10;
ap_uint<4> second_digit_2 = seconds/10;
ap_uint<4> minute_digit_1 = minutes%10;
ap_uint<4> minute_digit_2 = minutes/10;
ap_uint<4> hours_digit_1 = hours%10;
ap_uint<4> hours_digit_2 = hours/10;
ap_uint<8> segment_data;
ap_uint<8> segment_enable;
static ap_uint<3> state = 0;
switch (state) {
// second
case 0:
segment_data   = seven_segment_code[second_digit_1];
segment_enable = 0b11111110;
delay(250000L);
state = 1;
break;
case 1:
segment_data   = seven_segment_code[second_digit_2];
segment_enable = 0b11111101;
state = 2;
delay(250000L);
break;
// minutes
case 2:
segment_data   = seven_segment_code[minute_digit_1];
segment_enable = 0b11110111;
state = 3;
delay(250000L);
break;
case 3:
segment_data   = seven_segment_code[minute_digit_2];
segment_enable = 0b11101111;
state = 4;
delay(250000L);
break;
// hours
case 4:
segment_data   = seven_segment_code[hours_digit_1];
segment_enable = 0b10111111;
state = 5;
delay(250000L);
break;
case 5:
segment_data   = seven_segment_code[hours_digit_2];
segment_enable = 0b01111111;
state = 0;
delay(250000L);
break;
default:
segment_data   = seven_segment_code[0];
segment_enable = 0b11111111;
state = 0;
delay(250000L);
break;
}
seven_segment_data = segment_data;
seven_segment_enable = segment_enable;
}

 

综合这些代码后,使用 Vivado 工具将它们连接在一起并生成 FPGA 比特流。

FPGA

对电路板编程后,可以看到下图:

FPGA





审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分