[TOC]
# 1. Parallel to Serial
## Top Function (Kernel)
### In HLS
``` cpp=
void parallel2serial (
ap_uint<N> a,
bool &d,
bool &serial_start,
bool &serial_end,
bool begin
) {
#pragma HLS INTERFACE ap_none port=a
#pragma HLS INTERFACE ap_none port=d
#pragma HLS INTERFACE ap_none port=serial_start
#pragma HLS INTERFACE ap_none port=serial_end
#pragma HLS INTERFACE ap_none port=begin
#pragma HLS INTERFACE ap_ctrl_none port=return
static int count = N; //32-bit register
if (begin == 1) {
count = 0;
}
if (count == 0) {
serial_start = 1;
serial_end = 0;
} else if (count == N-1) {
serial_start = 0;
serial_end = 1;
d = a[count];
count = N;
} else if (count < N-1) {
serial_start = 0;
serial_end = 0;
d = a[count++];
} else {
serial_start = 0;
serial_end = 0;
count = N;
}
}
```
#### Code Explanation
- `a` is the N-bit parallel input signal
- `d` is the serial output signal
- When `begin` rise, `serial_start` pulse.
- The 32-bit register `count` start counting.
- Wait until the MSB of `a` is transferred to serial, `serial_end` rise.
- When the system start to transfer parallel signal to serial, `begin` should be 0.
#### Output

#### Utilization in HLS

- 33 FF's. 32 for 32-bit register `count`, and 1 is added by HLS.
#### Waveform in HLS

- The HLS code executes in every clock cycle.
- At the first clock cycle, `begin` pulse, `start` pulse, the LSB of `a` transferred to `d`.
- At the 8th clock cycle, transfer has finished, `serial_end` pulse.
### In Verilog
``` verilog=
`define PARALLEL_N 32'd8
module parallel2serial (
input clk,
input rst,
input begin_r,
input [7:0] a,
output reg d,
output reg serial_start,
output reg serial_end
);
reg [31:0] count; // 32-bit register
reg [31:0] next_count;
always @* begin
if (begin_r ==1'b1) begin
count = 32'd0;
end
if (count == 32'd0) begin
serial_start = 1'b1;
serial_end = 1'b0;
next_count = count + 1'b1;
d = a[count];
end
else if (count == `PARALLEL_N - 1'b1) begin
serial_start = 1'b0;
serial_end = 1'b1;
next_count = `PARALLEL_N;
d = a[count];
end
else if (count < `PARALLEL_N - 1'b1) begin
serial_start = 1'b0;
serial_end = 1'b0;
next_count = count + 1'b1;
d = a[count];
end
else begin
serial_start = 1'b0;
serial_end = 1'b0;
next_count = `PARALLEL_N;
d = 'bx;
end
end
always @(posedge clk) begin
if (rst)
count <= `PARALLEL_N;
else
count <= next_count;
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
`define PARALLEL_N 32'd8
module VIC_TESTBENCH();
reg clk; // period: 10ns
reg rst; // active high, synchronous
reg begin_r; // the begin signal
reg [7:0] in_parallel; // parallel input
wire d_hw; // output each clk cycle
wire serial_start; // the start signal
wire serial_end; // the end signal
reg [7:0] serial_out; // serial output
integer i;
// include the design under test
design_1_wrapper DUT0 (.a(in_parallel),
.ap_clk(clk),
.ap_rst(rst),
.begin_r(begin_r),
.d(d_hw),
.serial_start(serial_start),
.serial_end(serial_end));
/*
parallel2serial DUT1 (.a(in_parallel)
.clk(clk),
.rst(rst),
.begin_r(begin_r),
.d(d_hw),
.serial_start(serial_start),
.serial_end(serial_end));
*/
// 10ns clock generator
initial begin
clk = 1;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
in_parallel = 8'b11010011;
serial_out = 8'b00000000; // initial value
// reset active high
rst = 1'b1;
begin_r = 1'b0;
// reset fall, begin to transfer parallel signal to serial.
#10 rst = 1'b0;
#0 @(posedge clk) begin_r <= 1'b1;
// for loop
for (i = 0; i < `PARALLEL_N; i = i + 1) begin
@(posedge clk) begin
begin_r <= 1'b0;
serial_out[i] <= d_hw;
$display("d = %b, serial_start = %b, serial_end = %b", d_hw, serial_start, serial_end);
end
end
// Compare the result
#1
if (in_parallel != serial_out) begin
$display("Error, in_parallel = %b, output = %b". in_parallel, serial_out);
end
else begin
$display("Test Passed!");
end
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design.

- Then, use verilog to write a testbench.
#### Output

#### Utilization

- 32 FF's for 32-bit register
#### Waveform

- Same as the waveform of HLS
### DUT (Verilog)
#### Utilization

- 32 FF's for registers.
#### Waveform

- Same as the waveform of DUT(IP).
--------------------------------------------------
# 2. Serial to Parallel
## Top Function (Kernel)
### In HLS
``` cpp=
void serial2parallel(bool serial_start, bool &end_conversion, bool d, ap_uint<N> &a) {
#pragma HLS INTERFACE ap_none port=serial_start
#pragma HLS INTERFACE ap_none port=end_conversion
#pragma HLS INTERFACE ap_none port=d
#pragma HLS INTERFACE ap_none port=a
#pragma HLS INTERFACE ap_ctrl_none port=return
static ap_uint<N> state_reg = 0;
static ap_uint<N> a_reg_out = 0;
static unsigned int counter = N;
unsigned int next_counter;
ap_uint<N> next_state = state_reg;
next_counter = counter;
if (serial_start == 1) {
next_counter = 0;
}
if (next_counter < N-1) {
next_state = (next_state >> 1) | (d, (ap_uint<N-1>)0);;
next_counter++;
end_conversion = 0;
} else if (next_counter == N-1) {
next_state = (next_state >> 1) | (d, (ap_uint<N-1>)0);;
next_counter++;
a_reg_out = next_state;
end_conversion = 1;
} else {
end_conversion = 0;
}
counter = next_counter;
state_reg = next_state;
a = a_reg_out;
}
```
#### Code Explanation
- `d` is the serial input, `a` is the N-bit parallel output.
- `serial_start` rise, start transfering serial input to parallel.
- `end_conversion` will rise after finished the transfer.
#### Output

#### Utilization in HLS

- 49 FF's. 32 for 32-bit register `counter`, 8 for`state_reg`, another 8 for `a_reg_out`, and 1 is adding by HLS.
#### Waveform in HLS

- As `serial_start` pulse, start passing value.
- The parallel output `a[7:0]` shows up at the same time when `end_conversion` pulse.
### In Verilog
``` verilog=
`define N 32'd8
module serial2parallel(
input clk,
input rst,
input serial_start,
input d,
output reg end_conversion,
output reg [7:0] a
);
reg [7:0] a_reg;
reg [3:0] counter;
reg [3:0] next_counter;
always @* begin
if (serial_start == 1'b1) begin
a_reg = {d, a_reg[7:1]};
next_counter = 4'd1;
end_conversion = 1'b0;
a = 8'd0;
end
else if (next_counter == `N - 1'b1) begin
a_reg = {d, a_reg[7:1]};
next_counter = counter + 1'b1;
end_conversion = 1'b0;
a = 8'd0;
end
else if (next_counter == `N - 1'b1) begin
a_reg = {d, a_reg[7:1]};
next_counter = counter + 1'b1;
end_conversion = 1'b1;
a = a_reg;
end
else begin
a_reg = 8'd0;
next_counter = `N;
end_conversion = 1'b0;
a = 8'd0;
end
end
always @(posedge clk) begin
if (rst) begin
counter <= 4'd8;
end
else begin
counter <= next_counter;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
`define WIDTH 32'd8
module VIC_TESTBENCH();
reg clk; // 10ns clk
reg rst; // active high, synchronous
reg [0:0] d; // serial input
reg serial_start; // the start signal
wire [`WIDTH-1:0] a; // parallel output
wire end_conversion; // the end signal
reg [`WIDTH-1:0] data; // the data which will transferred from serial to parallel
integer i;
// include the design under test
design_1_wrapper DUT (.ap_clk(clk),
.ap_rst(rst),
.d(d),
.serial_start(serial_start),
.a(a),
.end_conversion(end_conversion));
// 10ns clk generator
initial begin
clk = 1;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
// initial value
d = 1'b0;
data = 8'b01001101;
// at the begining, rst stay high
rst = 1'b1;
serial_start = 1'b0;
// after 10ns, rst fall, serial_start rise at the next clk cycle
#10 rst = 0;
#0 @(posedge clk) begin
serial_start <= 1'b1;
d <= data[0];
$display("%b", data[0]);
// if we displayed 'd' here, it will
// display the value of the last clk cycle.
end
// for-loop
for (i = 1; i < `WIDTH; i = i + 1) begin
@(posedge clk) begin
serial_start <= 1'b0;
d <= data[i];
$display("%b", data[i]);
end
end
// Compare the value after a short delay
#1
if (data != a) begin
$display("Error, parallel output = %b, expected output = %b", a, data);
end
else begin
$display("%b", a);
$display("Test Passed!");
end
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design.

- Then, use verilog to write a testbench.
#### Output
- LSB -> MSB

#### Utilization

- 47 FF's. 32 for 32-bit register `count`, 15 for other variables.
#### Waveform

- Same as the waveform of HLS
### DUT (Verilog)
#### Output

#### Utilization

- Since I only let `counter`, `next_counter` store values in FFs, there are only 4 registers for 4-bit `counter`.
-
#### Waveform

-----------------------------------------------------
# 3. Combination Lock
## Top Function (Kernel)
### In HLS
- First, use `typedef` create 5 states
``` cpp=
typedef enum {s0, s2, s23, s234, s2346} state_type;
```
- Then, create a function which generate the 8-bit code of 7-segment display.
``` cpp=15
ap_uint<8> get_seven_segment_code(state_type number) {
#pragma HLS INLINE
ap_uint<8> code = seven_segment_code[0];
switch(number) {
case s0:
code = seven_segment_code[0];
break;
case s2:
code = seven_segment_code[1];
break;
case s23:
code = seven_segment_code[2];
break;
case s234:
code = seven_segment_code[3];
break;
case s2346:
code = seven_segment_code[4];
break;
default:
break;
}
return code;
}
```
- Where seven_segment_code is:
- a: bit 0, b: bit 1....., h: bit 7.
``` cpp=2
const ap_uint<8> seven_segment_code[10] = {
0b00000011, //0
0b10011111, //1
0b00100101, //2
0b00001101, //3
0b10011001, //4
0b01001001, //5
0b01000001, //6
0b00011111, //7
0b00000001, //8
0b00001001 //9
};
```
- Then, here is the main function.
- Only when the `enter` is high can we input a password(2346)
``` cpp=42
void combination_lock(
ap_uint<4> x,
bool enter,
bool &door_open,
bool lock,
ap_uint<8> &seven_segment_data,
ap_uint<4> &seven_segment_enable) {
#pragma HLS PIPELINE
#pragma HLS INTERFACE ap_none port=x
#pragma HLS INTERFACE ap_none port=enter
#pragma HLS INTERFACE ap_none port=door_open
#pragma HLS INTERFACE ap_none port=lock
#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
//--------state variables-----------------------------
static state_type state = s0;
state_type next_state;
//--------temporary output variables------------------
bool door_open_local = 0;
//--------switch case---------------------------------
switch(state) {
case s0:
if (enter == 1) {
if (x == 2) {
next_state = s2;
} else {
next_state = s0;
}
} else {
next_state = s0;
}
door_open_local = 0;
break;
case s2:
if (enter == 1) {
if (x == 3) {
next_state = s23;
} else {
next_state = s0;
}
} else {
next_state = s2;
}
door_open_local = 0;
break;
case s23:
if (enter == 1) {
if (x == 4) {
next_state = s234;
} else {
next_state = s0;
}
} else {
next_state = s23;
}
door_open_local = 0;
break;
case s234:
if (enter == 1) {
if (x == 6) {
next_state = s2346;
door_open_local = 1;
} else {
next_state = s0;
door_open_local = 0;
}
} else {
next_state = s234;
door_open_local = 0;
}
break;
case s2346:
if (lock == 1) {
next_state = s0;
door_open_local = 0;
} else {
next_state = s2346;
door_open_local = 1;
}
break;
default:
break;
}
//--------state and output variable assignments------------
state = next_state;
door_open = door_open_local;
seven_segment_data = get_seven_segment_code(state);
seven_segment_enable = 0b1110;
}
```
#### Output in HLS

- Enter the passwords by:
- 1 -> 2 -> 3 -> 1 -> 2 -> 3 -> 4 -> 6 -> ...
- door unlock when password 2346 is input.
- `door_open` return when it finished executing the function in kernel. If we try to get the return value at the same time we input our password in verilog, it will get the value of the last clock cycle, since we use register to store the state and then return the value of which state we are in.
#### Utilization in HLS

- 9 FF's.
#### Waveform in HLS

### In Verilog
``` verilog=
`define S0 4'd0
`define S2 4'd1
`define S23 4'd2
`define S234 4'd3
`define S2346 4'd4
mmodule cobination_lock (
input clk,
input rst,
input [3:0] x,
input enter,
input lock,
output reg door_open,
output reg [7:0] ssd_data,
output reg [3:0] ssd_enable
);
reg [3:0] state;
reg [7:0] ssd_data;
reg [0:0] next_door_open;
always @* begin
case (state)
`S0:
begin
if (enter == 1'b1) begin
if (x == 4'd2) begin
next_state = `S2;
end
else begin
next_state = `S0;
end
end
else begin
next_state = `S0;
end
next_door_open = 1'b0;
end
`S2:
begin
if (enter == 1'b1) begin
if (x == 4'd3) begin
next_state = `S23;
end
else begin
next_state = `S0;
end
end
else begin
next_state = `S2;
end
next_door_open = 1'b0;
end
`S23:
begin
if (enter == 1'b1) begin
if (x == 4'd4) begin
next_state = `S234;
end
else begin
next_state = `S0;
end
end
else begin
next_state = `S23;
end
next_door_open = 1'b0;
end
`S234:
begin
if (enter == 1'b1) begin
if (x == 4'd6) begin
next_state = `S2346;
next_door_open = 1'b1;
end
else begin
next_state = `S0;
next_door_open = 1'b0;
end
end
else begin
next_state =`S234;
next_door_open = 1'b0;
end
end
`S2346:
begin
if (lock == 1'b1) begin
next_state = `S0;
next_door_open = 1'b0;
end
else begin
next_state = `S2346;
next_door_open = 1'b1;
end
end
default:
begin
next_state = state;
next_door_open = dor_open;
end
endcase
ssd_data = get_ssd(state);
ssd_enable = 4'b1110;
end
always @(posedge clk) begin
if (rst) begin
state <= `S0;
door_open <= 1'b0;
end
else begin
state <= next_state;
door_open <= next_door_open;
end
end
functon [7:0] get_ssd;
input [3:0] state;
begin
case (state)
4'd0: get_ssd = 8'b00000011;
4'd1: get_ssd = 8'b10011111;
4'd2: get_ssd = 8'b00100101;
4'd3: get_ssd = 8'b00001101;
4'd4: get_ssd = 8'b10011001;
4'd5: get_ssd = 8'b01001001;
4'd6: get_ssd = 8'b01000001;
4'd7: get_ssd = 8'b00011111;
4'd8: get_ssd = 8'b00000001;
4'd9: get_ssd = 8'b00001001;
default: get_ssd = 8'b00000011;
endcase
end
endfunction
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
module VIC_TESTBENCH();
reg clk; // 10ns clk
reg rst; // reset
reg [3:0] x; // input password
reg enter; // enter the password
reg lock; // if the door is unlocked, we can use this signal to lock the door.
wire door_open; // to check whether the door is opened.
wire [7:0] seven_segment_data; // the seven-segment display
wire [3:0] seven_segment_enable; // the seven-segment display
design_1_wrapper DUT (.ap_clk(clk),
.ap_rst(rst),
.x(x),
.enter(enter),
.lock(lock),
.door_open(door_open),
.seven_segment_data(seven_segment_data),
.seven_segment_enable(seven_segment_enable));
/*
combination_lock (.clk(clk),
.rst(rst),
.x(x),
.enter(enter),
.lock(lock),
.door_open(door_open),
.ssd_data(seven_segment_data),
.ssd_enable(seven_segment_enable));
*/
// 10ns clk generator
initial begin
clk = 1'b0;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
// initialize the value
rst = 1'b1;
x = 4'd0;
enter = 1'b0;
lock = 1'b0;
// after 50ns, rst fall
#50 rst = 1'b0;
// Then input your password
@(posedge clk) begin
x <= 4'd1;
enter <= 1'b1;
end
// Input as many times as you want.
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design

#### Utilization

- 4 FF's
#### Waveform


- Same as the waveform of HLS
### DUT (Verilog)
#### Utilization

#### Waveform

---
# 4. Timer
## Top Function (Kernel)
### In HLS
``` cpp=
typedef enum{idle, running} timer_state_type;
void timer(ap_uint<N> n, bool start, bool &end) {
#pragma HLS INTERFACE ap_none port=start
#pragma HLS INTERFACE ap_none port=end
#pragma HLS INTERFACE ap_none port=n
#pragma HLS INTERFACE ap_ctrl_none port=return
static timer_state_type state = idle;
static unsigned long long int timer_variable = 0;
timer_state_type next_state;
unsigned long long int next_timer_variable;
bool end_local;
switch(state) {
case idle:
if (start == 1) {
next_state = running;
end_local = 0;
next_timer_variable = 0;
} else {
next_state = idle;
end_local = 0;
next_timer_variable = 0;
}
break;
case running:
if (timer_variable == n-1) {
next_state = idle;
end_local = 1;
next_timer_variable = 0;
} else {
next_timer_variable = timer_variable + 1;
next_state = running;
end_local = 0;
}
break;
default:
break;
}
state = next_state;
timer_variable = next_timer_variable;
end = end_local;
}
```
#### Code Explanation
- If the `start` signal is 1, the `time_variable` start counting, when `time_variable` counted to `n`, `end` rise and change the state to `idle`.
#### Output in HLS
- Our goal is to inspect the signals and we don't have any specific computation, our testbench doesn't check the output. Therefore, the testbench always claims that the design is correct.

- End when n = 20
#### Utilization in HLS

- 66 FF's
#### Waveform in HLS

- Takes 20 clk cycles (325ns-525ns).
### In Verilog
``` verilog=
`define IDLE 1'b0
`define RUNNING 1'b1
module timer (
input clk,
input rst,
input [15:0] n,
input start_r,
output reg end_r
);
reg [0:0] state;
reg [0:0] next_state;
reg [63:0] time_var;
reg [63:0] next_time_var;
always @* begin
case (state)
`IDLE:
begin
if (start_r == 1'b1) begin
next_state = `RUNNING;
next_time_var = 64'd0;
end_r = 1'b0;
end
else begin
next_state = `IDLE;
next_time_var = 64'd0;
end_r = 1'b0;
end
end
`RUNNING:
begin
if (time_var == n = 1'b1) begin
next_state = `IDLE;
next_time_var = 64'd0;
end_r = 1'b1;
end
else begin
next_state = `RUNNING;
next_time_var = time_var + 1'b1;
end_r = 1'b0;
end
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state <= `IDLE;
time_var <= 64'd0;
end
else begin
state <= next-state;
time_var <= next_time_var;
end
end
endmodule
```
## Testbench
- We can use a blocking assignment in a procedural block in a Verilog testbench to identify our input. In a testbench, the primary purpose is to simulate and verify the functionality of the design under test (DUT).
- It's important to remember that using blocking assignment in a preocedural block is specifically for testbenches and simulation purposes. In the actual hardware design, we should stick to using non-blocking assignments in sequential blocks to ensure correct and reliable simulation results. But for testbenches, using blocking assignments for input initialization is perfectly acceptable.
``` verilog=
module VIC_TESTBENCH();
reg clk; // 10ns clk
reg rst; // active high, synchronous reset
reg [15:0] n; // input number
reg timer_start; // start signal
wire timer_end; // end signal
integer i = 0;
integer j = 0;
// design under test
design_1_wrapper DUT (.ap_clk(clk),
.ap_rst(rst),
.n(n),
.start_r(timer_start),
.end_r(timer_end)):
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
// initialize the value
rst = 1'b1;
n = 16'd0;
timer_start = 1'b0;
// rst fall after 50ns
#50 rst = 1'b0;
for (i = 0; i < 20; i = i + 1) begin
@(posedge clk) begin
$display("Cycle %02d, Start signal: %b, End signal: %b", i, timer_start, timer_end);
end
end
@(posedge clk) begin
timer_start = 1'b1;
$display("Cycle %02d, Start signal: %b, End signal: %b", j, timer_start, timer_end);
end
for (j = 0; j < 50; j = j + 1) begin
@(posedge clk) begin
timer_start = 1'b0;
$display("Cycle %02d, Start signal: %b, End signal: %b", j, timer_start, timer_end);
end
end
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design.

#### Output

- End when n = 20
#### Utilization

- 65 FF's
#### Waveform

- Takes 20 clk cyces (250ns-450ns), same as the waveform of HLS design.
### DUT (Verilog)
#### Utilization

- Same as IP
#### Waveform

-----------------------------------------------------
# 4. Debouncer
## Top Function (Kernel)
### In HLS
``` cpp=
#define DELAY_COUNTER 500L
typedef enum{transfer, delay} debouncer_state_type;
void debouncer(bool sw, bool &out) {
#pragma HLS INTERFACE ap_none port=sw
#pragma HLS INTERFACE ap_none port=out
#pragma HLS INTERFACE ap_ctrl_none port=return
static debouncer_state_type state = transfer;
static unsigned long long int counter = DELAY_COUNTER;
static bool previous_sw = 0;
unsigned long long int next_counter;
static debouncer_state_type next_state;
bool out_tmp = 0;
switch(state) {
case transfer:
if (previous_sw != sw) {
next_state = delay;
} else {
next_state = transfer;
}
next_counter = DELAY_COUNTER;
out_tmp = sw;
break;
case delay:
if (counter == 0) {
next_state = transfer;
next_counter = DELAY_COUNTER;
} else {
next_counter = counter - 1;
next_state = delay;
}
out_tmp = previous_sw;
break;
default:
break;
}
previous_sw = out_tmp;
state = next_state;
counter = next_counter;
out = out_tmp;
}
```
#### Code Explanation
- If the previous sw: `previous_sw` is not equal to the sw(now): `sw`, it means that the signal is bouncing. Change the state to `delay`, and stay when `DELAY_COUNTER` count to 0.
#### Utilization in HLS

- 67 FF's for registers.
#### Waveform in HLS

- We can see that the area between 2 blue markers is the delay time.
### In Verilog
``` verilog=
`define DELAY_COUNTER 64'd500
`define TRANSFER 1'b0
`define DELAY 1'b1
module debouncer (
input clk,
input rst,
input sd,
output reg out_r
);
reg [0:0] previous_sw;
reg [0:0] out_tmp;
reg [63:0] counter;
reg [63:0] next_counter;
reg [0:0] state;
reg [0:0] next_state;
always @* begin
case (state)
`TRANSFER:
begin
if (previous_sw != sw) begin
next_state = `DELAY;
end
else begin
next_state = `TRANSFER;
end
next_counter = `DELAY_COUNTER;
out_tmp = sw;
end
`DELAY
begin
if (counter == 64'd0) begin
next_state = `TRANSFER;
next_counter = `DELAY_COUNTER;
end
else begin
next_state = `DELAY;
next_counter = counter - 1'b1;
end
out_tmp = previous_sw;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
out_r <= 1'b0;
state <= `TRANSFER;
counter <= `DELAY_CONTER;
end
else begin
out_r <= out_tmp;
state <= next_state;
counter <= next_counter;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
module VIC_TESTBENCH();
reg clk; // the 10ns clk
reg rst; // active high, synchronous reseet
reg sw; // the signal that hasn't been debounced
wire debounced_out; // the debounced signal
integer i;
// design under test
design_1_wrapper DUT (.ap_clk(clk),
.ap_rst(rst),
.sw(sw),
.out_r(debounced_out));
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
// initialize the value
rst = 1'b1;
sw = 1'b0;
// rst fall after 50ns
#50 @(posedge clk) rst = 1'b0;
// delay for a long time in order to check the debounced value more easier.
#5000
// push the button, bouncing
for (i = 0; i < 250; i = i + 1) begin
@(posedge clk) sw = 1'b0;
@(posedge clk) sw = 1'b1;
end
// stable
for (i = 0; i < 5000; i = i + 1) begin
@(posedge clk) sw = 1'b1;
end
// release the button, bouncing
for (i = 0; i < 250; i = i + 1) begin
@(posedge clk) sw = 1'b1;
@(posedge clk) sw = 1'b0;
end
// stable at the end
for (i = 0; i < 5000; i = i + 1) begin
@(posedge clk) sw = 1'b0;
end
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design in verilog

#### Utilization

- 66 FF's for registers.
#### Waveform

- Same as the waveform of HLS
### DUT (Verilog)
#### Utilization

#### Waveform

----------------------------------------------
# 6. Counter
## Top Function (Kernel)
### In HLS
``` cpp=
typedef enum{wait_for_one, wait_for_zero} counter_state_type;
void counter(
bool count_button,
ap_uint<8> &seven_segments_data,
ap_uint<4> &seven_segments_enable) {
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE ap_none port=count_button
#pragma HLS INTERFACE ap_none port=seven_segments_data
#pragma HLS INTERFACE ap_none port=seven_segments_enable
static ap_uint<5> number = 0;
static counter_state_type state = wait_for_one;
ap_uint<5> next_number;
counter_state_type next_state;
bool out_local;
switch(state) {
case wait_for_one:
if (count_button == 1) {
if (number+1 == 10) {
next_number = 0;
} else {
next_number = number+1;
}
next_state = wait_for_zero;
} else {
next_number = number;
next_state = wait_for_one;
}
break;
case wait_for_zero:
if (count_button == 1) {
next_number = number;
next_state = wait_for_zero;
} else {
next_number = number;
next_state = wait_for_one;
}
break;
default:
break;
}
number = next_number;
state = next_state;
// which will get the binary number of seven-segment code
seven_segments_data = get_seven_segment_code(number);
seven_segments_enable = 0b1110;
}
```
#### Utilization in HLS

- Uses 7 FFs for registers
#### Waveform in HLS

### In Verilog
``` verilog=
`define WAIT_FOR_ONE 1'b0
`define WAIT_FOR_ZERO 1'b0
module counter(
input wire clk,
input wire rst,
input wire [0:0] count_button,
output reg [7:0] seven_segments_data,
output reg [3:0] seven_segments_enable
);
reg [3:0] num;
reg [3:0] next_num;
reg [0:0] state;
reg [0:0] next_state;
// BCD to seven-segment
function [7:0] bcd2ssd;
input [3:0] number;
begin
case (number)
4'd0: bcd2ssd = 8'b11000000;
4'd1: bcd2ssd = 8'b11111001;
4'd2: bcd2ssd = 8'b10100100;
4'd3: bcd2ssd = 8'b10110000;
4'd4: bcd2ssd = 8'b10011001;
4'd5: bcd2ssd = 8'b10010010;
4'd6: bcd2ssd = 8'b10000010;
4'd7: bcd2ssd = 8'b11111000;
4'd8: bcd2ssd = 8'b10000000;
4'd9: bcd2ssd = 8'b10010000;
default: bcd2ssd = 8'b11000000;
endcase
end
endfunction
// main function of the testbench
always @* begin
case (state)
`WAIT_FOR_ONE:
if (count_button == 1'b1) begin
if (num + 1'b1 == 4'd10) begin
next_num = 4'd0;
end
else begin
next_num = num + 1'b1;
end
next_state = `WAIT_FOR_ZERO;
end
else begin
next_num = num;
next_state = `WAIR_FOR_ONE;
end
`WAIT_FOR_ZERO:
if (count_button == 1'b1) begin
next_num = num;
next_state = `WAIT_FOR_ZERO;
end
else begin
next_num = num;
next_state = `WAIT_FOR_ONE;
end
default:
begin
next_num = num;
next_state = state;
end
endcase
seven_segments_data = bcd2ssd(next_num);
seven_segments_enable = 4'b1110;
end
always @(posedge clk) begin
if (rst) begin
num <= 4'd0;
state <= `WAIT_FOR_ONE;
end
else begin
num <= next_num;
state <= next_state;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
module VIC_TESTBENCH();
reg clk;
reg rst;
reg [0:0] button;
wire [7:0] ssd_data;
wire [3:0] ssd_enable;
reg [3:0] ssd_number;
integer i;
// design under test
design_1_wrapper DUT0 (.ap_clk(clk),
.ap_rst(rst),
.count_button(button),
.seven_segments_data(ssd_data),
.seven_segments_enable(ssd_enable));
/*
count DUT1 (.ap_clk(clk),
.ap_rst(rst),
.count_button(button),
.seven_segments_data(ssd_data),
.seven_segments_enable(ssd_enable));
*/
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// ssd number
task ssd_number_generate;
input [7:0] ssd_data;
output [3:0] number;
begin
case (ssd_data)
8'b11000000: number = 4'd0;
8'b11111001: number = 4'd1;
8'b10100100: number = 4'd3;
8'b10011001: number - 4'd4;
8'b10010010: number = 4'd5;
8'b10000010: number = 4'd6;
8'b11111000: number = 4'd7;
8'b10000000: number = 4'd8;
8'b10010000: number = 4'd9;
default: number = 4'd0;
endcase
end
endtask
// main function of the testbench
initial begin
// initialize the value
rst = 1'b1;
button = 1'b0;
// rst fall
#125 rst = 1'b0;
for (i = 0; i < 10; i = i + 1) begin
@(posedge clk) button <= 1'b1;
#10
ssd_number_generate(ssd_data, ssd_number);
$display("count_up = %b, output = %d", button, ssd_number);
@(posedge clk) button <= 1'b0;
#10
ssd_number_generate(ssd_data, ssd_number);
$display("count_up = %b, output = %d", button, ssd_number);
end
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design

#### Utilization

- Uses 11 LUTs, and 6 FFs for registers.
#### Waveform

### DUT (Verilog)
#### Utilization

- Uses 10 LUTs, and 5 FFs for registers, which are less than IP.
#### Waveform

---------------------------------------------------
# 7. Clock Generator
## Top Function (Kernel)
### In HLS
``` cpp=
#define CLOCK_FREQUENCY_DIVISOR 20
typedef enum{zero, one} clock_state_type;
void clock_generator(bool &slow_clock_signal) {
#pragma HLS INTERFACE ap_none port=slow_clock_signal
#pragma HLS INTERFACE ap_ctrl_none port=return
static clock_state_type state = zero;
static unsigned int counter = CLOCK_FREQUENCY_DIVISOR /2-1;
clock_state_type next_state;
unsigned int next_counter;
bool slow_clock_signal_local;
switch(state) {
case zero:
if (counter == 0) {
next_counter = CLOCK_FREQUENCY_DIVISOR /2-1;
next_state = one;
} else {
next_counter = counter-1;
next_state = zero;
}
slow_clock_signal_local = 0;
break;
case one:
if (counter == 0) {
next_counter = CLOCK_FREQUENCY_DIVISOR /2-1;
next_state = zero;
} else {
next_counter = counter-1;
next_state = one;
}
slow_clock_signal_local = 1;
break;
default:
break;
}
state = next_state;
counter = next_counter;
slow_clock_signal = slow_clock_signal_local;
}
```
- Utilization in HLS

- Waveform of HLS waveform viewer

### In Verilog
``` verilog=
`define ZERO 1'b0
`define ONE 1'b1
`define CLK_FREQ_DIV 32'd20
module clock_generator (
input clk,
input rst,
output slow_clk_signal
);
reg slow_clk_signal;
reg tmp_clk_signal;
reg [31:0] counter;
reg [31:0] next_counter;
reg [0:0] state;
reg [0:0] next_state;
always @* begin
case (state)
`ZERO:
begin
if (counter == 32'd0) begin
next_counter = `CLK_FREQ_DIV / 2 - 1'b1;
next_state = `ONE;
end
else begin
next_counter = counter - 1'b1;
next_state = `ZERO
end
tmp_clk_signal = 1'b0;
end
`ONE:
begin
if (counter == 32'd0) begin
next_counter = `CLK_FREQ_DIV / 2 - 1'b1;
next_state = `ZERO;
end
else begin
next_counter = counter - 1'b1;
next_state = `ONE;
end
tmp_clk_signal = 1'b1;
end
default:
begin
next_counter = `CLK_FREQ_DIV / 2 - 1'b1;
next_state = `ZERO;
tmp_clk_signal = 1'b0;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
slow_clk_signal <= 1'b0;
counter <= `CLK_FREQ_DIV /2 - 1'b1;
state <= `ZERO;
end
else begin
slow_clk_signal <= tmp_clk_signal;
counter <= next_counter;
state <= next_state;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
module VIC_TESTBENCH();
reg clk;
reg rst;
wire slow_clk_signal;
integer i;
// design under test
design_1_wrapper DUT0 (.ap_clk(clk),
.ap_rst(rst),
.slow_clock_signal(slow_clk_signal));
/*
clock_generator DUT1 (.clk(clk),
.rst(rst),
.slow_clk_signal(slow_clk_signal));
*/
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// main function of testbench
initial begin
rst = 1'b1;
#50 @(posedge clk) rst = 1'b0;
for (i = 0; i < 100; i = i + 1) begin
@(posedge clk) begin
$display("%b", slow_clk_signal);
end
end
end
endmodule
```
### DUP (IP)
- Export RTL IP and create block design

#### Utilization

#### Waveform

### DUP (Verilog)
#### Utilization

- More LUTs and FFs then DUT(IP).
#### Wavefrom

- clk appears 50ns later then DUT(IP).
# 8. Pulse Generator
## Top Function (Kernel)
### In HLS
``` cpp=
typedef enum{w1, w0} pulse_gen_states_type;
void pulse_generator(bool input, bool &pulse) {
#pragma HLS INTERFACE ap_none port=input
#pragma HLS INTERFACE ap_none port=pulse
#pragma HLS INTERFACE ap_ctrl_none port=return
static pulse_gen_states_type state = w1;
pulse_gen_states_type next_state;
bool next_pulse;
switch(state) {
case w1:
if (input == 1) {
next_state = w0;
next_pulse = 1;
} else {
next_state = w1;
next_pulse = 0;
}
break;
case w0:
if (input == 1) {
next_state = w0;
next_pulse = 0;
} else {
next_state = w1;
next_pulse = 0;
}
break;
default:
break;
}
state = next_state;
pulse = next_pulse;
}
```
#### Utilization in HLS

#### Waveform Viewer (from HLS)

### In Verilog
``` verilog=
`define W0 1'b0
`define W1 1'b1
module pulse_generator (
input clk,
input rst,
input in_signal,
output reg pulse
);
reg state;
reg next_state;
always @* begin
case (state)
`W1:
begin
if (in_signal == 1'b1) begin
next_state = W0;
pulse = 1'b1;
end
else begin
next_state = `W1;
pulse = 1'b0;
end
end
`W0:
begin
if (in_signal == 1'b1) begin
next_state = `W0;
pulse = 1'b0;
end
else begin
next_state = `W1;
pulse = 1'b0;
end
end
default:
begin
next_state = `W1;
pulse = 1'b0;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state <= `W1;
end
else begin
state <= next_state;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog=
module VIC_TESTBENCH();
reg clk;
reg rst;
reg [0:0] in_signal;
wire pulse;
// design under test
design_1_wrapper DUT0 (.ap_clk(clk),
.ap_rst(rst),
.input_r(in_signal),
.pulse(pulse));
/*
pulse_generator DUT1 (.clk(clk),
.rst(rst),
.in_signal(in_signal),
.pulse(pulse));
*/
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// main function of the testbench
initial begin
rst = 1'b1;
in_signal = 1'b0;
#125 @(posedge clk) rst = 1'b1;
#50 @(posedge clk) in_signal <= 1'b1;
#50 in_signal = 1'b0;
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design

#### Utilization


#### Waveform

### DUT (Verilog)
#### Utilization


- Same as HLS design
#### Waveform

# 9. Single Cycle Regular Pulses
## Top Function (Kernel)
### In HLS
``` cpp=
#define PULSE_PERIOD 20
typedef enum{zero, one} states_type;
void single_cycle_regular_pulses(bool &periodic_pulses) {
#pragma HLS INTERFACE ap_none port=periodic_pulses
#pragma HLS INTERFACE ap_ctrl_none port=return
static states_type state = zero;
static unsigned int counter = PULSE_PERIOD-1;
states_type next_state;
unsigned int next_counter;
bool periodic_pulses_local;
switch(state) {
case zero:
if (counter == 1) {
next_counter = counter-1;
next_state = one;
} else {
next_counter = counter-1;
next_state = zero;
}
periodic_pulses_local = 0;
break;
case one:
next_counter = PULSE_PERIOD-1;
next_state = zero;
periodic_pulses_local = 1;
break;
default:
break;
}
state = next_state;
counter = next_counter;
periodic_pulses = periodic_pulses_local;
}
```
#### Utilization in HLS

#### Waveform Viewer

### In Verilog
``` verilog=
`define ZERO 1'b0
`define ONE 1'b1
`define PULSE_PERIOD 32'd20
module single_cycle_regular_pulse(
input clk,
input rst,
output reg periodic_pulses
);
reg [31:0] counter;
reg [31:0] next_counter;
reg [0:0] state;
reg [0:0] next_state;
always @* begin
case (state)
`ZERO:
begin
if (counter == 32'd1) begin
next_counter = counter - 1'b1;
next_state = `ONE;
end
else begin
next_counter = counter - 1'b1;
next_state = `ZERO;
end
periodic_pulses = 1'b0;
end
`ONE:
begin
next_counter = `PULSE_PERIOD - 1'b1;
next_state = `ZERO;
periodic_pulses = 1'b1;
end
default:
begin
next_counter = counter - 1'b1;
next_state = `ZERO;
periodic_pulses = 1'b1;
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state <= `ZERO;
counter <= `PULSE_PERIOD - 1'b1;
end
else begin
state <= next_state;
counter <= next_counter;
end
end
endmodule
```
## Testbench
- Testbench in Verilog
``` verilog
module VIC_TESTBENCH();
reg clk;
reg rst;
wire periodic_pulses;
// design under test
design_1_wrapper DUT0 (.ap_clk(clk),
.ap_rst(rst),
.periodic_pulses(periodic_pulses));
/*
single_cycle_regular_pulse DUT1 (.clk(clk),
.rst(rst),
.periodic_pulses(periodic_pulses));
*/
// 10ns clk generator
initial begin
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
// main function of the testbench
initial begin
rst = 1'b1
#100 @(posedge clk) rst = 1'b0;
end
endmodule
```
### DUT (IP)
- Export RTL IP and create block design in vivado

#### Utilization

#### Waveforn

### DUT (Verilog)
#### Utilization

#### Waveform
