Main Content

Transmit and Receive FIFO Registers

This example shows how to generate HDL 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 HDL 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

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 HDL 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 HDL 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 a New HDL Coder Project for the Receive FIFO

Run this command at the MATLAB command prompt to create a new HDL Coder project for the receive FIFO:

coder -hdlcoder -new mlhdlc_rx_fifo

When the HDL Code Generation pane opens, set the mlhdlc_rx_fifo.m function as the MATLAB function to generate HDL code for. Set the mlhdlc_rx_fifo_tb.m script as the MATLAB test bench. Click Workflow Advisor.

Refer to Get Started with MATLAB to HDL Workflow for a more complete tutorial on creating and populating MATLAB HDL Coder™ projects.

Generate HDL Code for the Receive FIFO

Right-click HDL Code Generation and select Run to selected task to run all the steps from the beginning through the HDL code generation.

Examine the generated HDL code for the receive FIFO by clicking the hyperlinks in the bottom pane.

Create a New HDL Coder Project for the Transmit FIFO

coder -hdlcoder -new mlhdlc_tx_fifo

When the HDL Code Generation pane opens, specify mlhdlc_tx_fifo.m as the MATLAB function to generate HDL code for the transmit FIFO function, and mlhdlc_tx_fifo_tb.m as the MATLAB test bench. Click Workflow Advisor.

Generate HDL Code for the Transmit FIFO

Right-click HDL Code Generation and select Run to selected task to run all the steps from the beginning through the HDL code generation.

Examine the generated HDL code for the transmit FIFO by clicking on the hyperlinks in the bottom pane.

Related Topics