Use o matlab para gerar ondas senoidais, ondas de amor e números de ponto flutuante de precisão simples para arquivos coe binários (a profundidade de armazenamento e a largura de bits de dados são ajustáveis)

Use o matlab para gerar ondas senoidais, ondas de amor e números de ponto flutuante de precisão simples para arquivos coe binários (a profundidade de armazenamento e a largura de bits de dados são ajustáveis)


prefácio

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


Dica: Segue o texto deste artigo, todos originais do próprio autor, escrever um artigo não é fácil, e espero que seja útil para todos.

1. O formato do arquivo coe

No ISE, os arquivos de inicialização são necessários para a geração do núcleo ROM ou RAM IP.

O formato é o seguinte:

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

        A primeira linha de código informa ao vivado que nossos dados estão armazenados no arquivo coe em formato binário, que pode ser alterado para qualquer outro sistema que você queira escrever.

        Após o sinal de igual na segunda linha estão os dados binários armazenados. Preste atenção ao formato, os dados anteriores terminam com vírgula e os últimos dados terminam com ponto e vírgula.

Em segundo lugar, o formato de representação de dados binários

        Na verdade, os dados gravados no arquivo coe podem ser gravados diretamente em números inteiros por conveniência, sem considerar a conversão do código binário original, código inverso e código complementar, mas porque usei o formato binário ao escrever números de ponto flutuante no coe, porque escrever números de ponto flutuante em arquivos coe só pode ser binário (como representar números de ponto flutuante em binário não será descrito aqui), então a onda senoidal e a onda love são gravadas no arquivo coe em formato binário.

        Como são dados binários, é necessário revisar o método de representação binária aqui, porque era um pouco estranho para esse formato na época porque trabalhei com meus colegas de equipe na noite de segunda-feira por muito tempo, então sempre havia alguns bugs em programação.

        Existem três formas de binário: código original, código complementar e código complementar .

        O código original, o código inverso e o código complementar de números positivos são todos iguais , então não há necessidade de se preocupar muito. Por exemplo, +6 é expresso como 0_110 em um número binário de 4 bits, o primeiro 0 é o bit de sinal e a regra do bit de sinal é 0 positivo e 1 negativo. Então o código original, o código inverso e o código complementar de +6 são todos 0_110.

        O que precisamos prestar atenção é o número negativo. O código original do número negativo é o mesmo que o código original do número positivo correspondente, exceto pelo bit de sinal . Por exemplo, -6 é representado por um binário de 4 bits número, então seu código original é 1_110. O código inverso de um número negativo é inverter o bit de sinal do código original . Por exemplo, -6 é representado por um número binário de 4 bits, então seu código inverso é 1_001. O complemento de um número negativo é adicionar 1 ao complemento do código Por exemplo, -6 é representado por um número binário de 4 bits, então seu complemento é 1_010.

        Deve-se observar que os números positivos e negativos no computador são expressos na forma de código de complemento , portanto, no computador final, +6 é expresso como número binário de 4 bits, que é 0_110, e -6 é expresso como 4 -bit número binário, que é 1_010.

Três, onda senoidal

1. Código MATLAB

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);%关闭文件 

código 2.vivado

O núcleo ROM IP é usado.

Código de nível superior:

`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

Código de simulação:

`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

resultado:

Após a saída dos resultados da simulação vivado, preste atenção para definir o formato de dados primeiro :

 Após a configuração, você pode ver a seguinte onda senoidal:

4. Ondas de amor

1. Código MATLAB

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);%关闭文件 

 código 2.vivado

        Este código é o mesmo que o código vivado na onda senoidal.Você só precisa alterar os dados do arquivo coe no núcleo IP para armazenar os dados da onda de amor.

 5. Código MATLAB para converter números de ponto flutuante de precisão simples em dados de coe binários

 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);

Depois de escrever fica assim:

         Observe que esse formato tem um pequeno BUG, ​​e não otimizei o programa. Depois de escrever, preciso alterar manualmente a vírgula no final da penúltima linha para o ponto e vírgula da primeira -última linha. Após a alteração, ele estará em conformidade com o formato do arquivo coe, pode ser colocado no núcleo IP.


Resumir

        O texto acima é todo o conteúdo que quero compartilhar hoje, espero que seja útil para todos.

Acho que você gosta

Origin blog.csdn.net/m0_66360845/article/details/127530448
Recomendado
Clasificación