有关用HDL Coder生成Verilog的资料实在太少,且大多是由Simulink搭建模块生成。笔者经过初步探索,将MATLAB代码直接通过HDL Coder生成Verilog代码的过程总结于此。
以一个最大值为15可加减计数器为例
在MATLAB上方的APP里找到HDL Coder,HDL Coder需要MATLAB Function和MATLAB Testbench两个文件,第一个即纯粹的函数or算法,第二个需要对其进行调用并保证能现在MATLAB上成功运行。
这里已经将两个文件添加了进去,添加完毕后再Workflow Advisor里设置生成的代码为Verilog,再运行即可。里面还可以设置仿真工具并生成testbench,但笔者尝试用生成的testbench进行仿真,并不能成功运行,且代码本身就杂乱非常。
这里给出counter.m和counter_tb.m两段代码
function [count] = counter(clk, rst)
persistent state
if isempty(state) || ~rst
state = 0;
elseif clk
state = state + 1;
if state == 16
state = 1;
end
end
count = state;
end
function counter_tb
% 创建时间和输入信号
time = 0:19;
clk = [0, ones(1, 9), 0, ones(1, 9)]; % 50% 占空比,10个时钟周期
rst = [0, ones(1, 19)]; % 第一个周期的复位信号高
% 初始化用于存储输出的数组
count_out = zeros(size(time));
% 模拟计数器
for i = 1:length(time)
count_out(i) = counter(clk(i), rst(i))
end
end
在Workflow Advisor中运行后会生成.v文件,保存的路径可以在左侧选HDL Code Generation下查看,这里给出生成的verilog代码,可以发现可读性比较差,自己在分析时加了些中文注释。
// -------------------------------------------------------------
// Generated by MATLAB 9.7, MATLAB Coder 4.3 and HDL Coder 3.15
//
//
//
// -- -------------------------------------------------------------
// -- Rate and Clocking Details
// -- -------------------------------------------------------------
// Design base rate: 1
//
//
// Clock Enable Sample Time
// -- -------------------------------------------------------------
// ce_out 1
// -- -------------------------------------------------------------
//
//
// Output Signal Clock Enable Sample Time
// -- -------------------------------------------------------------
// count ce_out 1
// -- -------------------------------------------------------------
//
// -------------------------------------------------------------
// -------------------------------------------------------------
//
// Module: counter_fixpt
// Source Path: counter_fixpt
// Hierarchy Level: 0
//
// -------------------------------------------------------------
//生成的是可加可减的计数器
// reset置0, rst置1, clk_enable置1 时可用,clk_1为1时加,为0时减
`timescale 1 ns / 1 ns
module counter_fixpt
(clk,
reset,
clk_enable,
clk_1,
rst,
ce_out,
count);
input clk;
input reset;
input clk_enable;
input clk_1; // ufix1
input rst; // ufix1
output ce_out;
output [3:0] count; // ufix4
wire enb;
wire state_not_empty;
reg state_not_empty_1;
wire tmp;
wire tmp_1;
wire tmp_2;
wire tmp_3;
wire [4:0] state; // ufix5
wire [4:0] state_1; // ufix5
reg [4:0] state_2; // ufix5
wire [4:0] state_3; // ufix5
wire tmp_4;
wire [4:0] tmp_5; // ufix5
wire [4:0] tmp_6; // ufix5
wire [4:0] tmp_7; // ufix5
// HDL code generation from MATLAB function: counter_fixpt_trueregionp7
assign state_not_empty = 1'b1;
assign enb = clk_enable;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// %
//
// Generated by MATLAB 9.7 and Fixed-Point Designer 6.4 %
//
// %
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
assign tmp = ! state_not_empty_1 || ( ! (rst != 1'b0)); // rst为0或state_not_empty_1为0时,temp为1,都为1时temp为0
assign tmp_1 = (tmp == 1'b0 ? state_not_empty_1 :
state_not_empty); // 永远为1
always @(posedge clk or posedge reset)
begin : state_not_empty_reg_process
if (reset == 1'b1) begin
state_not_empty_1 <= 1'b0;
end
else begin
if (enb) begin // clk_enable置1时有效,state_not_empty_1为1
state_not_empty_1 <= tmp_1;
end
end
end
assign tmp_2 = ! state_not_empty_1 || ( ! (rst != 1'b0)); // 都1时为0,正常运作时两参数为1,tmp_2为0
assign tmp_3 = clk_1 != 1'b0; // clk_1为1时加,为0时减————tmp_3也为1、0
// HDL code generation from MATLAB function: counter_fixpt_trueregionp13
assign state = 5'b00001;
// HDL code generation from MATLAB function: counter_fixpt_trueregionp2
assign state_1 = 5'b00000;
// HDL code generation from MATLAB function: counter_fixpt
assign state_3 = state_2 + 5'b00001;
assign tmp_4 = state_3 == 5'b10000; // 代表计数器是否满15,是为1
// HDL code generation from MATLAB function: counter_fixpt_trueregionp10
assign tmp_5 = (tmp_4 == 1'b0 ? state_3 :
state); // 若超过01111则置00001,代表计数从15回到1,否则正常加一
always @(posedge clk or posedge reset) // reset高电平复位
begin : state_reg_process
if (reset == 1'b1) begin
state_2 <= 5'b00000;
end
else begin
if (enb) begin
state_2 <= tmp_6;
end
end
end
// HDL code generation from MATLAB function: counter_fixpt_falseregionp2
assign tmp_7 = (tmp_3 == 1'b0 ? state_2 :
tmp_5); // tmp_3 == 0时为减法,执行state_2 即tmp_6,此时正常运转tmp_2为0,执行tmp_7(??)tmp_3 == 1时为加法,执行tmp_5。
assign tmp_6 = (tmp_2 == 1'b0 ? tmp_7 :
state_1);
assign count = tmp_6[3:0];
assign ce_out = clk_enable;
endmodule // counter_fixpt
自己编写一个testbench在Modelsim上进行仿真,发现结果是可靠的,reset置0, rst置1, clk_enable置1 时可用,clk_1为1时加,为0时减。
`timescale 1 ps/ 1 ps
module counter_fixpt_tb();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg clk_1;
reg clk_enable;
reg reset;
reg rst;
// wires
wire ce_out;
wire [3:0] count;
parameter clk_period = 10;
// assign statements (if any)
counter_fixpt i1 (
// port map - connection between master ports and signals/registers
.ce_out(ce_out),
.clk(clk),
.clk_1(clk_1),
.clk_enable(clk_enable),
.count(count),
.reset(reset),
.rst(rst)
);
// reset置0, rst置1, clk_enable置1 时可用,clk_1为1时加,为0时减
initial
clk = 0;
always #(clk_period/2) clk = ~clk; // 时钟
initial begin
reset = 1;
# 10 reset = 0;
end // 使能
initial begin
rst = 0;
# 10 rst = 1;
end // 使能
initial begin
clk_enable = 0;
# 10 clk_enable = 1;
end // 使能
initial clk_1 = 0;
always #(clk_period) clk_1 = {$random} % 2; //clk_1为随机的0或1
endmodule
这里与自己编写同样功能的计数器效果进行对比,自己写的verilog代码就简单易懂了许多,同样编写testbench仿真结果一致。文章来源:https://www.toymoban.com/news/detail-739975.html
module counter(
input clk,
input rst,
input add_sub, // 0 for subtract, 1 for add
output reg [3:0] count
);
always @(posedge clk or negedge rst) begin
if (rst == 0) begin
count <= 4'b0000; // Reset the counter to 0
end else if (add_sub) begin
if (count == 4'b1111) begin
count <= 4'b0000; // Wrap around to 0 if max value reached
end else begin
count <= count + 1; // Increment the counter
end
end else begin
if (count == 4'b0000) begin
count <= 4'b1111; // Wrap around to max value if 0 reached
end else begin
count <= count - 1; // Decrement the counter
end
end
end
endmodule
尽管仿真显示二者的功能一致,但从代码来看区别还是很大的,用QuartusII对.v文件进行编译再生成RTL电路图,可以更加直观地发现区别,前者明显更繁琐且消耗资源更多。若是在面向具体项目的实际设计中,或者在更加负责的系统或算法的设计中,HDL Coder生成的代码便可能不合适。
文章来源地址https://www.toymoban.com/news/detail-739975.html
到了这里,关于MATLAB生成Verilog代码——HDL Coder使用初探的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!