High-Level Synthesis Code Generation for Transmit and Receive FIFO Registers
This example shows how to generate High-Level Synthesis (HLS) code from MATLAB® code that models the data transfer between a transmit and receive first-in, first-out (FIFO) register or buffer. This example contains two functions that represent a receive FIFO buffer and a transmit FIFO buffer, and a test bench mlhdlc_fifo_tb
that simulates the data transfer that occurs between the two buffers. Each function is hardware-ready and exhibits good practices and guidelines to follow when writing MATLAB functions to generate efficient HLS code. For more information on guidelines to follow, see Guidelines for Writing MATLAB Code to Generate Efficient HDL and HLS Code.
View Example Functions and Test Bench
You can set up the model and open the MATLAB design for the transmit FIFO and the receive FIFO.
type('mlhdlc_rx_fifo');
function [dout, empty, byte_ready, full, bytes_available] = ... mlhdlc_rx_fifo(get_byte, store_byte, byte_in, reset_fifo, fifo_enable) % % Copyright 2014-2015 The MathWorks, Inc. % % First In First Out (FIFO) structure. % This FIFO stores integers. % The FIFO is actually a circular buffer. % persistent head tail fifo byte_out handshake if (reset_fifo || isempty(head)) head = 1; tail = 2; byte_out = 0; handshake = 0; end if isempty(fifo) fifo = zeros(1,1024); end full = 0; empty = 0; byte_ready = 0; % Section for checking full and empty cases if ((tail == 1 && head == 1024) || ((head + 1) == tail)) empty = 1; end if ((head == 1 && tail == 1024) || ((tail + 1) == head)) full = 1; end % handshaking logic if get_byte == 0 handshake = 0; end if handshake == 1 byte_ready = 1; end if (fifo_enable == 1) %%%%%%%%%%%%%%get%%%%%%%%%%%%%%%%%%%%% if (get_byte && ~empty && handshake == 0 ) head = head + 1; if head == 1025 head = 1; end byte_out = fifo(head); byte_ready = 1; handshake = 1; end %%%%%%%%%%%%%put%%%%%%%%%%%%%%%%%%%%% if (store_byte && ~full) fifo(tail) = byte_in; tail = tail + 1; if tail == 1025 tail = 1; end end end % Section for calculating num bytes in FIFO if (head < tail) bytes_available = (tail - head) - 1; else bytes_available = (1024 - head) + tail - 1; end dout = byte_out; end
type('mlhdlc_tx_fifo');
function [dout, empty, byte_received, full, bytes_available, dbg_fifo_enable] = ... mlhdlc_tx_fifo(get_byte, store_byte, byte_in, reset_fifo, fifo_enable) % % Copyright 2014-2015 The MathWorks, Inc. % % First In First Out (FIFO) structure. % This FIFO stores integers. % The FIFO is actually a circular buffer. % persistent head tail fifo byte_out handshake if (reset_fifo || isempty(head)) head = 1; tail = 2; byte_out = 0; handshake = 0; end if isempty(fifo) fifo = zeros(1,1024); end full = 0; empty = 0; byte_received = 0; % Section for checking full and empty cases if ((tail == 1 && head == 1024) || ((head + 1) == tail)) empty = 1; end if ((head == 1 && tail == 1024) || ((tail + 1) == head)) full = 1; end % handshaking logic if store_byte == 0 handshake = 0; end if handshake == 1 byte_received = 1; end if (fifo_enable == 1) %%%%%%%%%%%%%%get%%%%%%%%%%%%%%%%%%%%% if (get_byte && ~empty) head = head + 1; if head == 1025 head = 1; end byte_out = fifo(head); end %%%%%%%%%%%%%put%%%%%%%%%%%%%%%%%%%%% if (store_byte && ~full && handshake == 0) fifo(tail) = byte_in; tail = tail + 1; if tail == 1025 tail = 1; end byte_received = 1; handshake = 1; end end % Section for calculating num bytes in FIFO if (head < tail) bytes_available = (tail - head) - 1; else bytes_available = (1024 - head) + tail - 1; end dout = byte_out; dbg_fifo_enable = fifo_enable; end
Open the MATLAB design for the test bench that exercises both designs. This test bench test both the transmit and receive FIFOs. However, when generating HLS code, because you have individual functions for the transmit and receive FIFOs, you need individual test benches to test both functions and generate code. For simulation purposes, you can use mlhdlc_fifo_tb
, but for HLS code generation, use the receive FIFO test bench mlhdlc_rx_fifo_tb
with the receive FIFO function mlhdlc_rx_fifo
, and use the transmit FIFO test bench mlhdlc_tx_fifo
with the transmit FIFO function mlhdlc_tx_fifo
.
type('mlhdlc_fifo_tb');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % simulation parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % data payload creation % Copyright 2014-2015 The MathWorks, Inc. messageASCII = 'Hello World!'; message = double(unicode2native(messageASCII)); msgLength = length(message); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TX_FIFO core %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% numBytesToFifo = 1; tx_get_byte = 0; tx_full = 0; tx_byte_received = 0; i1 = 1; while (numBytesToFifo <= msgLength && ~tx_full) % first thing the processor does is clear the internal tx fifo if i1 == 1 tx_reset_fifo = 1; mlhdlc_tx_fifo(0, 0, 0, tx_reset_fifo, 1); else tx_reset_fifo = 0; end if (i1 > 1) tx_data_in = message(numBytesToFifo); numBytesToFifo = numBytesToFifo + 1; tx_store_byte = 1; while (tx_byte_received == 0) [tx_data_out, tx_empty, tx_byte_received, tx_full, tx_bytes_available] = ... mlhdlc_tx_fifo(tx_get_byte, tx_store_byte, tx_data_in, tx_reset_fifo, 1); end tx_store_byte = 0; while (tx_byte_received == 1) [tx_data_out, tx_empty, tx_byte_received, tx_full, tx_bytes_available] = ... mlhdlc_tx_fifo(tx_get_byte, tx_store_byte, tx_data_in, tx_reset_fifo, 1); end end i1 = i1 + 1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Transfer Bytes from TX FIFO to RX FIFO %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% i1 = 1; tx_get_byte = 0; tx_store_byte = 0; tx_data_in = 0; tx_reset_fifo = 0; rx_get_byte = 0; rx_data_in = 0; rx_reset_fifo = 0; while (tx_bytes_available > 0) if i1 == 1 rx_reset_fifo = 1; mlhdlc_rx_fifo(0, 0, 0, rx_reset_fifo, 1); else rx_reset_fifo = 0; end if (i1 > 1) tx_get_byte = 1; rx_store_byte = 1; [tx_data_out, tx_empty, tx_byte_received, tx_full, tx_bytes_available] = ... mlhdlc_tx_fifo(tx_get_byte, tx_store_byte, tx_data_in, tx_reset_fifo, 1); rx_data_in = tx_data_out; [rx_data_out, rx_empty, rx_byte_ready, rx_full, rx_bytes_available] = ... mlhdlc_rx_fifo(rx_get_byte, rx_store_byte, rx_data_in, rx_reset_fifo, 1); end i1 = i1 + 1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % RX_FIFO core %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% numBytesFromFifo = 1; rx_store_byte = 0; rx_byte_received = 0; i1 = 1; msgBytes = zeros(1,msgLength); while (~rx_empty) % first thing the processor does is clear the internal rx fifo if (i1 > 1) rx_get_byte = 1; while (rx_byte_ready == 0) [rx_data_out, rx_empty, rx_byte_ready, rx_full, rx_bytes_available] = ... mlhdlc_rx_fifo(rx_get_byte, rx_store_byte, rx_data_in, rx_reset_fifo, 1); end msgBytes(i1-1) = rx_data_out; rx_get_byte = 0; while (rx_byte_ready == 1) [rx_data_out, rx_empty, rx_byte_ready, rx_full, rx_bytes_available] = ... mlhdlc_rx_fifo(rx_get_byte, rx_store_byte, rx_data_in, rx_reset_fifo, 1); end end i1 = i1 + 1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% numRecBytes = numBytesFromFifo; if sum(msgBytes-message) == 0 disp('Received message correctly'); else disp('Received message incorrectly'); end native2unicode(msgBytes)
Simulate the Design
Simulate the design with the test bench before generating code to ensure there are no runtime errors.
mlhdlc_fifo_tb
Received message correctly ans = 'Hello World!'
Create HDL Coder™ Project for the Receive FIFO
At the MATLAB command line, set up the path for HLS code generation by using the function hdlsetuphlstoolpath
.
Create a HDL Coder project for the receive FIFO.
coder -hdlcoder -new mlhdlc_rx_fifo
Add the file mlhdlc_rx_fifo.m
to the project as the MATLAB Function and mlhdlc_rx_fifo_tb.m
as the MATLAB Test Bench and then click Workflow Advisor.
Generate HLS Code for the Receive FIFO
In the HDL Workflow Advisor, select MATLAB to HLS as the Code Generation Workflow and Cadence Stratus as the Synthesis tool in Select Code Generation Target step.
Run all the steps from the beginning through the HLS code generation. Examine the generated HLS code for the receive FIFO by clicking the hyperlinks in the bottom pane.
For more information, see Get Started with MATLAB to High-Level Synthesis Workflow Using HDL Coder App.
Create HDL Coder Project for the Transmit FIFO
At the MATLAB command line, set up the path for HLS code generation by using the function hdlsetuphlstoolpath
.
Create a HDL Coder project.
coder -hdlcoder -new mlhdlc_tx_fifo
Add mlhdlc_tx_fifo.m
to the project as the MATLAB Function and mlhdlc_tx_fifo_tb.m
as the MATLAB Test Bench and then click Workflow Advisor.
Generate HLS Code for the Transmit FIFO
In the HDL Workflow Advisor, select MATLAB to HLS as the Code Generation Workflow and Cadence Stratus as the Synthesis tool in Select Code Generation Target step.
Run all the steps from the beginning through the HLS code generation. Examine the generated HLS code for the transmit FIFO by clicking on the hyperlinks in the bottom pane.