赞
踩
有关用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仿真结果一致。
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生成的代码便可能不合适。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。