绪论
该项目的目标是展示 HLS 在设计数字系统方面的能力。为此,本文展示如何在 HLS 中描述数字时钟。
时钟在 7 段数码管上显示小时、分钟和秒。
它有两种操作模式:时钟和设置。时钟模式是标准模式,在此模式下,当前时间显示在数码管上。在设置模式下,可以使用按钮设置时间。
下图显示开发板上的时钟配置。
如下图所示,该设计主要分为三个模块:秒时钟发生器、数字时钟引擎和显示驱动。
下面的流水线循环用于实现秒时钟发生器。
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 段数码管上显示当前时间。
#includeconst 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 比特流。
对电路板编程后,可以看到下图:
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !