目录
设计中经常用到一些控制逻辑,如有限状态机(FSM),如果用各种block搭建一个FSM比较麻烦。System Generator支持调用MATLAB代码,通常可以编写MATLAB代码来实现FSM等控制逻辑,通过MCode block调用到System Generator设计中。
本文将使用MATLAB代码设计一个FSM,对“1010”这个序列进行检测。序列检测应该是很多Verilog/VHDL学习者在学习FSM时接触到的一个简单设计。本文将以该设计在System Generator中的实现为主题,介绍MCode的使用。
1. 有限状态机设计
1.1 FSM代码编写
FPGA相关知识点14——有限状态机FSM设计 - 哔哩哔哩 (bilibili.com)https://www.bilibili.com/read/cv7207512?spm_id_from=333.999.0.0其实,我们在写if/else语句和switch/case语句的时候,就是在跟状态机打交道。如果可以把整个系统模型抽象成一个有限状态机,那么代码就会逻辑特别清晰,结构特别规整。
序列检查状态机设计:
这是一个非常常见的状态机应用,本次设计用来检测序列“1010”
本人设计流程如下:
1. 确定有效状态:
本次需要检测序列“1010”,那么就应该会出现5个有效状态,为:
“初始状态” -> “检测到1” -> “检测到10” -> “检测到101” -> “检测到1010”
那么状态变量需要的数据宽度就是3,此时最多能表示8个状态。
我们的有效状态只有5个,剩下的都归为异常状态。
状态机如下:
对着图写程序,把每一个状态变化的情况编写出来。使用到的语法就是switch/case语法。
% mcode只能调用function函数文件
function Match = state_machine_1010(Din)
% 在mcode文件中,状态变量state需要由下式定义
persistent state, state = xl_state(0,{xlUnsigned, 3, 0});
switch state
case 0
if Din == true %表示输入为1(1真,0假)布尔型输入
state = 1;
else
state = 0;
end
Match = 0; %每一个状态都要有一个输出,因为FPGA是并行运算的
case 1
if Din == true
state = 1;
else
state = 2;
end
Match = 0;
case 2
if Din == true
state = 3;
else
state = 0;
end
Match = 0;
case 3
if Din == true
state = 1;
else
state = 4;
end
Match = 0;
case 4
if Din == true
state = 3;
else
state = 0;
end
Match = 1;
%要注意的是,异常状态也是要设计的,一般会让它们回归到状态0
otherwise
state = 0;
Match = 0;
end
在MATLAB中,persistent变量是函数中的局部变量,它在函数调用之间保留其值。当MATLAB首次遇到特定的persistent语句时,它将persistent变量初始化为空矩阵([])。当您清除或修改内存中的函数时,MATLAB会清除persistent变量。要保留函数在内存中,请使用mlock。
在我的例子中,xl_state是一个persistent变量,它被初始化为0,并且在每次调用函数时保留其值。{xlUnsigned, 3, 0}是一个单元阵列,其中xlUnsigned代表数据类型是无符号的定点数;3代表数据的位宽,因为代码中的state需要达到4,所以至少要3bit的位宽;0代表的是二进制点的位置,该部分代码不需要有小数,所以直接设置为0。
注意,因为本文与FPGA视频“Mcode调用流程”相关联,因此这里是用matlab编写的程序。如果是Verilog语言会有些不同。同时matlab中的状态机功能会受到限制,不能使用matlab所有功能函数,如FFT等就不能放在状态机中
1.2 输入序列代码编写
我们也需要在matlab写出输入序列的代码
%% 系统参数
seq = {0,0,0,1,1,0,1,0,1,0,1,1,1,0,1,0};
N = length(seq);
vi = seq;
match = zeros(1,N);
for n = 1:N
match(n) = state_machine_1010(seq(n)); %调用FSM,将每一位信号按顺序输入有限状态机
end
1.3. mcode概念
MCode用于在Simulink环境下执行MATLAB函数,经常用于实现一些简单的算法功能、有限状态机和控制逻辑。
基本规则:
- 所有的输入和输出必须是Xilinx的定点数据类型(xfix);
- 至少包含一个输出;
- M文件应在MATLAB的搜索路径下,或与slx模型文件在同一目录。
*建议先设计好.m文件,再使用Mcode模块。
支持的语法:
Mcode只支持一些在Verilog中也轻易实现的matlab代码,包括:
- 赋值(等号左边只能有一个变量);
- if/else/elseif end语法(条件表达式必须是判断true/false或1/0);
- switch语法(case只能选择常量)、for语法;
- 加法、减法、乘法、除法(除数必须是2的N次幂,因为可以转换为移位),除此之外,不支持其它算术表达式
- 关系运算符(<、<=、>、>=、==、~=)
- 逻辑运算符(&、|、~)
三种数据类型:
无符号定点数(xlUnsigned)、带符号定点数(xlSigned)、布尔值(xlBoolean)。
如果在编写matlab时使用到了浮点型,需要手动转化为定点型,如,将浮点数π转换为xfix类型的matlab代码如下:
x = xfix({xlSigned, 20, 16, xlRound, xlWrap}, 3.1415926);
转换后为Fix_20_16格式,Round量化,Wrap溢出
非常需要注意的是:
Matlab代码是一种顺序执行的程序,但我们FPGA最大的特点就是并行工作。所以我们在设计matlab程序的时候一定要考虑到这一点。具体来讲,那就是要保证所有变量在运行的过程中都能得到确定的值。比如说,当我们用matlab设计了一个if else语句时,如果有一些情况你没有考虑进去,没有确定该情况下的赋值结果。那么,那些本来在顺序执行时下不会出现的情况,在并行运行时一定会冒出来,而这些情况得到的结果就都是错误的了。
2. Simulink
2.1. 输入部分
计数器 | ROM |
![]() |
|
2.2. Mcode模块
2.3. 完整模块
仿真结果如下
总结
在System Generator中,Black Box和M-Code都是用于将HDL文件导入进行设计的工具。Black Box是一种可重用的模块,它可以将HDL文件导入到System Generator中进行设计。Black Box可以使用Vivado Simulator或外部协同仿真器进行仿真。Black Box的优点是可以快速地将HDL文件导入到System Generator中进行设计,而不需要手动创建模块。但是,Black Box的缺点是它不能提供与HDL文件相同的灵活性和控制。
相比之下,M-Code可以提供更高的灵活性和控制。M-Code允许用户使用MATLAB语言编写自定义代码,并将其与System Generator模块集成在一起。M-Code的优点是可以提供更高的灵活性和控制,因为用户可以使用MATLAB语言编写自定义代码。但是,M-Code的缺点是需要更多的时间和精力来编写和调试代码。首先,M-Code需要更多的时间和精力来编写和调试代码。其次,M-Code的性能可能会受到影响,因为它需要调用MATLAB引擎来执行代码。此外,M-Code可能会受到System Generator的限制,例如,它可能无法访问System Generator中的所有变量和对象。