Use matlab to generate sine waves, heart waves, and single-precision floating-point numbers to binary coe files (storage depth and data bit width are adjustable)

Use matlab to generate sine waves, heart waves, and single-precision floating-point numbers to binary coe files (storage depth and data bit width are adjustable)


foreword

  某个周一晚上和队友搞那个正弦波的coe文件搞到了12点多,在网上也没找到合适的,于是下定决心自己写一个,在此记录一下,顺带发了个生成爱心波和浮点数的coe文件。本文用matlab生成正弦波、爱心波以及单精度浮点数转二进制的coe文件(存储深度与数据位宽可调)。


Tip: The following is the text of this article, all of which are original by the author himself. Writing an article is not easy, and I hope it will be helpful to everyone.

1. The format of the coe file

In ISE, initialization files are required for ROM or RAM IP core generation.

The format is as follows:

memory_initialization_radix = 2;
memory_initialization_vector = 
111111011011,
111111100111,
111111110100;

        The first line of code tells vivado that our data is stored in the coe file in binary form, which can be changed to any other system you want to write.

        After the equal sign on the second line is the stored binary data. Pay attention to the format, the previous data ends with a comma, and the last data ends with a semicolon.

Second, the representation format of binary data

        In fact, the data written into the coe file can be directly written in integers for convenience, without considering the conversion of binary original code, inverse code, and complement code, but because I used the binary format when writing floating-point numbers into the coe file, because writing Floating-point numbers to coe files can only be binary (how to represent floating-point numbers in binary will not be described here), so the sine wave and love wave are written into the coe file in binary format.

        Since it is binary data, it is necessary to review the binary representation method here, because it was a bit unfamiliar to this format at that time because I worked with my teammates on Monday night for a long time, so there were always some bugs in programming.

        There are three forms of binary: original code, complement code, and complement code .

        The original code, inverse code, and complement code of positive numbers are all the same , so there is no need to worry too much. For example, +6 is expressed as 0_110 in 4-bit binary number, the first 0 is the sign bit, and the rule of the sign bit is 0 positive and 1 negative. Then the original code, inverse code and complement code of +6 are all 0_110.

        What we need to pay attention to is the negative number. The original code of the negative number is the same as the original code of the corresponding positive number except for the sign bit . For example, -6 is represented by a 4-bit binary number, then its original code is 1_110. The inverse code of a negative number is to invert the sign bit of the original code . For example, -6 is represented by a 4-bit binary number, then its inverse code is 1_001. The complement of a negative number is to add 1 to the complement of the code . For example, -6 is represented by a 4-bit binary number, then its complement is 1_010.

        It should be noted that both positive and negative numbers in the computer are expressed in the form of complement code , so in the final computer, +6 is expressed as 4-bit binary number, which is 0_110, and -6 is expressed as 4-bit binary number, which is 1_010.

Three, sine wave

1. MATLAB code

clear all;
close all;
depth=2^12;  %存储器的深度
width=12;    %width为二进制数据位宽
N=0:depth-1;
y_write=zeros(depth,1);
y=ceil((2^(width-1)-1)*sin(2*pi *N/depth)); %正弦波
 plot(y,'m','LineWidth',2);

fid=fopen('sin.coe','w');
fprintf(fid,'memory_initialization_radix=2;\n');
fprintf(fid,'memory_initialization_vector=\n'); 
for i=1:depth
    if (y(1,i)<0)   
        y_write(i,1)=y(1,i)+2^(width-1);%负数用补码表示
    else
        y_write(i,1)=y(1,i);
    end
end
for i=1:depth
    if (y(1,i)<0)   
        y_bin=dec2bin(y_write(i,1),width-1);
        if(i == depth)
            fprintf(fid,'%c','1'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c;',y_bin(width-1));
        else
            fprintf(fid,'%c','1'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c,\n',y_bin(width-1));
        end
    else
        y_bin=dec2bin(y_write(i,1),width-1);
        if(i == depth)
            fprintf(fid,'%c','0'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c;',y_bin(width-1));        
        else
            fprintf(fid,'%c','0'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c,\n',y_bin(width-1));  
        end
    end
end
fclose(fid);%关闭文件 

2.vivado code

The ROM IP core is used.

Top level code:

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/10/25 15:37:36
// Design Name: 
// Module Name: rom_test
// Project Name: 
// Target Devices: 
// Tool Versions: 2017.4
// Description: 
// Dependencies: 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//

module rom_test(
input clk,
output [11:0] dout
    );

reg [11:0] address=0;
always @(posedge clk) begin
    address<=address+1;
end
rom_ip u1_rom_ip (
  .clka(clk),    // input wire clka
  .addra(address),  // input wire [11 : 0] addra
  .douta(dout)  // output wire [11 : 0] douta
);

endmodule

Simulation code:

`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/10/25 15:37:59
// Design Name: 
// Module Name: rom_test_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 2017.4
// Description: 
// Dependencies: 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module rom_test_tb;
// rom_test Parameters
parameter PERIOD  = 2;
// rom_test Inputs
reg   clk                                  = 0 ;
// rom_test Outputs
wire  [11:0]  dout                         ;

initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

rom_test  u_rom_test (
    .clk                     ( clk          ),
    .dout                    ( dout  [11:0] )
);

endmodule

result:

After the vivado simulation results come out, pay attention to setting the data format first :

 After setting, you can see the following sine wave:

4. Love waves

1. MATLAB code

clear all;
close all;
depth=2^12;  %存储器的深度
width=12;    %width为二进制数据位宽
N=0:depth-1;
y_write=zeros(depth,1);
%爱心波
a=10;
b5=1:depth;
y = real(round((2^(width-2)/4-4)*(abs((b5-depth/2)/1000).^(2/3)+(0.9*sqrt((3.3-((b5-depth/2)/1000).^2))).*sin(a*pi*((b5-depth/2))/1000)+1.8)));
plot(y,'m','LineWidth',2);

fid=fopen('sin.coe','w');
fprintf(fid,'memory_initialization_radix=2;\n');
fprintf(fid,'memory_initialization_vector=\n'); 
for i=1:depth
    if (y(1,i)<0)   
        y_write(i,1)=y(1,i)+2^(width-1);%负数用补码表示
    else
        y_write(i,1)=y(1,i);
    end
end
for i=1:depth
    if (y(1,i)<0)   
        y_bin=dec2bin(y_write(i,1),width-1);
        if(i == depth)
            fprintf(fid,'%c','1'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c;',y_bin(width-1));
        else
            fprintf(fid,'%c','1'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c,\n',y_bin(width-1));
        end
    else
        y_bin=dec2bin(y_write(i,1),width-1);
        if(i == depth)
            fprintf(fid,'%c','0'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c;',y_bin(width-1));        
        else
            fprintf(fid,'%c','0'); 
            for j=1:width-2
                fprintf(fid,'%c',y_bin(j));
            end
            fprintf(fid,'%c,\n',y_bin(width-1));  
        end
    end
end
fclose(fid);%关闭文件 

 2.vivado code

        This code is the same as the vivado code in the sine wave. You only need to change the coe file data in the IP core to store the love wave data.

 5. MATLAB code for converting single-precision floating-point numbers to binary coe data

 fid=fopen('single.coe','w');
 fprintf(fid,'memory_initialization_radix=2;\n');
 fprintf(fid,'memory_initialization_vector=\n');
Y=[1.2 2.2;2.3 -5.4];%要写的浮点数数据放置于矩阵中
N=2;%Y矩阵的行数
K=2;%Y矩阵的列数
for mm=1:N
    for nn=1:K
        for pp=1:32
           q=quantizer('single');
           bin=num2bin(q,Y(mm,nn));
           bin1=bin(pp);
           if(bin1=='1')
               bin2=1;
           else
               bin2=0;
           end
           fprintf(fid,'%d',bin2);
        end
    fprintf(fid,',\n');
    end
end
fprintf(fid,';');
fclose(fid);

After writing it is as follows:

         Note that this format has a little BUG, ​​and I have not optimized the program. After writing, I need to manually change the comma at the end of the second-to-last line to the semi-colon of the first-to-last line. After the change, it will conform to the format of the coe file , can be put into the IP core.


Summarize

        The above is all the content I want to share today, I hope it will be helpful to everyone.

Guess you like

Origin blog.csdn.net/m0_66360845/article/details/127530448