Skip to content

fpga项目:i2s dac自己仿写(驱动PCM5102A)

minichao9901 edited this page Dec 17, 2023 · 1 revision

草稿画时序图

image

开始写代码

  • 时钟:例化pll产生6MHz,进一步手写4分频产生1.5MHz。理论时钟需求是48kHz*32=1.536MHz,差不多就行了。
  • sin_rom模块:用256深度的case语句产生。用excel表产生。注意负数的补码转换公式为:-x+65536。例如-701的补码为-701+65536=64835
  • i2s_drv模块:按时序图手写,很简单。注意时序对齐,注意i2s_ws信号要提前i2s_din一拍,这是i2s标准协议要求
  • i2s_top模块,将这几个模块连起来。

rom模块生成excel表

image

代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/17 20:12:20
// Design Name: 
// Module Name: i2s_drv
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module i2s_drv(
    input clk_1p5m,
    input rst_n,    
    input [15:0] idata,
    
    output reg req,
    output i2s_din,
    output reg i2s_ws
    );
    
reg [4:0] cnt;
reg [15:0] idata_r;
reg req_r;

//cnt
always @(posedge clk_1p5m or negedge rst_n)
if(rst_n==0)
    cnt<=0;
else
    cnt<=cnt+1;

//req
always @(posedge clk_1p5m or negedge rst_n)
if(rst_n==0)
    req<=0;
else if(cnt==0 || cnt==16)
    req<=1;
else
    req<=0;
    
//req_r
always @(posedge clk_1p5m or negedge rst_n)
if(rst_n==0)
    req_r<=0;
else 
    req_r<=req;  
    
//idata_r
always @(posedge clk_1p5m or negedge rst_n)
if(rst_n==0)
    idata_r<=0;
else if(req_r==1)
    idata_r<=idata;  //reload data
else
    idata_r<=idata_r<<1; //begin to shift

//i2s_din
assign i2s_din=idata_r[15];

//i2s_ws
always @(*)
if(cnt>=2 && cnt<18)
    i2s_ws=0;
else
    i2s_ws=1;

    
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/17 20:13:28
// Design Name: 
// Module Name: rom_sine
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module rom_sine(
    input clk,
    input rst_n,
    input [7:0] addr,
    output reg [15:0] data
    );
    
always @(posedge clk or negedge rst_n)
if(rst_n==0)
    data<=0;
else
    case(addr)
        0 : data<= 16'd0;
        1 : data<= 16'd764;
        2 : data<= 16'd1527;
        3 : data<= 16'd2290;
        4 : data<= 16'd3051;
        5 : data<= 16'd3811;
        6 : data<= 16'd4568;
        7 : data<= 16'd5322;
        8 : data<= 16'd6073;
        9 : data<= 16'd6821;
        10 : data<= 16'd7564;
        11 : data<= 16'd8303;
        12 : data<= 16'd9036;
        13 : data<= 16'd9765;
        14 : data<= 16'd10487;
        15 : data<= 16'd11203;
        16 : data<= 16'd11913;
        17 : data<= 16'd12615;
        18 : data<= 16'd13310;
        19 : data<= 16'd13996;
        20 : data<= 16'd14674;
        21 : data<= 16'd15344;
        22 : data<= 16'd16004;
        23 : data<= 16'd16654;
        24 : data<= 16'd17295;
        25 : data<= 16'd17925;
        26 : data<= 16'd18544;
        27 : data<= 16'd19152;
        28 : data<= 16'd19748;
        29 : data<= 16'd20333;
        30 : data<= 16'd20905;
        31 : data<= 16'd21465;
        32 : data<= 16'd22012;
        33 : data<= 16'd22546;
        34 : data<= 16'd23066;
        35 : data<= 16'd23572;
        36 : data<= 16'd24064;
        37 : data<= 16'd24541;
        38 : data<= 16'd25004;
        39 : data<= 16'd25451;
        40 : data<= 16'd25883;
        41 : data<= 16'd26300;
        42 : data<= 16'd26701;
        43 : data<= 16'd27085;
        44 : data<= 16'd27454;
        45 : data<= 16'd27806;
        46 : data<= 16'd28141;
        47 : data<= 16'd28459;
        48 : data<= 16'd28760;
        49 : data<= 16'd29044;
        50 : data<= 16'd29310;
        51 : data<= 16'd29558;
        52 : data<= 16'd29789;
        53 : data<= 16'd30002;
        54 : data<= 16'd30197;
        55 : data<= 16'd30373;
        56 : data<= 16'd30531;
        57 : data<= 16'd30671;
        58 : data<= 16'd30793;
        59 : data<= 16'd30895;
        60 : data<= 16'd30980;
        61 : data<= 16'd31045;
        62 : data<= 16'd31092;
        63 : data<= 16'd31120;
        64 : data<= 16'd31130;
        65 : data<= 16'd31120;
        66 : data<= 16'd31092;
        67 : data<= 16'd31045;
        68 : data<= 16'd30980;
        69 : data<= 16'd30895;
        70 : data<= 16'd30793;
        71 : data<= 16'd30671;
        72 : data<= 16'd30531;
        73 : data<= 16'd30373;
        74 : data<= 16'd30197;
        75 : data<= 16'd30002;
        76 : data<= 16'd29789;
        77 : data<= 16'd29558;
        78 : data<= 16'd29310;
        79 : data<= 16'd29044;
        80 : data<= 16'd28760;
        81 : data<= 16'd28459;
        82 : data<= 16'd28141;
        83 : data<= 16'd27806;
        84 : data<= 16'd27454;
        85 : data<= 16'd27085;
        86 : data<= 16'd26701;
        87 : data<= 16'd26300;
        88 : data<= 16'd25883;
        89 : data<= 16'd25451;
        90 : data<= 16'd25004;
        91 : data<= 16'd24541;
        92 : data<= 16'd24064;
        93 : data<= 16'd23572;
        94 : data<= 16'd23066;
        95 : data<= 16'd22546;
        96 : data<= 16'd22012;
        97 : data<= 16'd21465;
        98 : data<= 16'd20905;
        99 : data<= 16'd20333;
        100 : data<= 16'd19748;
        101 : data<= 16'd19152;
        102 : data<= 16'd18544;
        103 : data<= 16'd17925;
        104 : data<= 16'd17295;
        105 : data<= 16'd16654;
        106 : data<= 16'd16004;
        107 : data<= 16'd15344;
        108 : data<= 16'd14674;
        109 : data<= 16'd13996;
        110 : data<= 16'd13310;
        111 : data<= 16'd12615;
        112 : data<= 16'd11913;
        113 : data<= 16'd11203;
        114 : data<= 16'd10487;
        115 : data<= 16'd9765;
        116 : data<= 16'd9036;
        117 : data<= 16'd8303;
        118 : data<= 16'd7564;
        119 : data<= 16'd6821;
        120 : data<= 16'd6073;
        121 : data<= 16'd5322;
        122 : data<= 16'd4568;
        123 : data<= 16'd3811;
        124 : data<= 16'd3051;
        125 : data<= 16'd2290;
        126 : data<= 16'd1527;
        127 : data<= 16'd764;
        128 : data<= 16'd0;
        129 : data<= 16'd64772;
        130 : data<= 16'd64009;
        131 : data<= 16'd63246;
        132 : data<= 16'd62485;
        133 : data<= 16'd61725;
        134 : data<= 16'd60968;
        135 : data<= 16'd60214;
        136 : data<= 16'd59463;
        137 : data<= 16'd58715;
        138 : data<= 16'd57972;
        139 : data<= 16'd57233;
        140 : data<= 16'd56500;
        141 : data<= 16'd55771;
        142 : data<= 16'd55049;
        143 : data<= 16'd54333;
        144 : data<= 16'd53623;
        145 : data<= 16'd52921;
        146 : data<= 16'd52226;
        147 : data<= 16'd51540;
        148 : data<= 16'd50862;
        149 : data<= 16'd50192;
        150 : data<= 16'd49532;
        151 : data<= 16'd48882;
        152 : data<= 16'd48241;
        153 : data<= 16'd47611;
        154 : data<= 16'd46992;
        155 : data<= 16'd46384;
        156 : data<= 16'd45788;
        157 : data<= 16'd45203;
        158 : data<= 16'd44631;
        159 : data<= 16'd44071;
        160 : data<= 16'd43524;
        161 : data<= 16'd42990;
        162 : data<= 16'd42470;
        163 : data<= 16'd41964;
        164 : data<= 16'd41472;
        165 : data<= 16'd40995;
        166 : data<= 16'd40532;
        167 : data<= 16'd40085;
        168 : data<= 16'd39653;
        169 : data<= 16'd39236;
        170 : data<= 16'd38835;
        171 : data<= 16'd38451;
        172 : data<= 16'd38082;
        173 : data<= 16'd37730;
        174 : data<= 16'd37395;
        175 : data<= 16'd37077;
        176 : data<= 16'd36776;
        177 : data<= 16'd36492;
        178 : data<= 16'd36226;
        179 : data<= 16'd35978;
        180 : data<= 16'd35747;
        181 : data<= 16'd35534;
        182 : data<= 16'd35339;
        183 : data<= 16'd35163;
        184 : data<= 16'd35005;
        185 : data<= 16'd34865;
        186 : data<= 16'd34743;
        187 : data<= 16'd34641;
        188 : data<= 16'd34556;
        189 : data<= 16'd34491;
        190 : data<= 16'd34444;
        191 : data<= 16'd34416;
        192 : data<= 16'd34406;
        193 : data<= 16'd34416;
        194 : data<= 16'd34444;
        195 : data<= 16'd34491;
        196 : data<= 16'd34556;
        197 : data<= 16'd34641;
        198 : data<= 16'd34743;
        199 : data<= 16'd34865;
        200 : data<= 16'd35005;
        201 : data<= 16'd35163;
        202 : data<= 16'd35339;
        203 : data<= 16'd35534;
        204 : data<= 16'd35747;
        205 : data<= 16'd35978;
        206 : data<= 16'd36226;
        207 : data<= 16'd36492;
        208 : data<= 16'd36776;
        209 : data<= 16'd37077;
        210 : data<= 16'd37395;
        211 : data<= 16'd37730;
        212 : data<= 16'd38082;
        213 : data<= 16'd38451;
        214 : data<= 16'd38835;
        215 : data<= 16'd39236;
        216 : data<= 16'd39653;
        217 : data<= 16'd40085;
        218 : data<= 16'd40532;
        219 : data<= 16'd40995;
        220 : data<= 16'd41472;
        221 : data<= 16'd41964;
        222 : data<= 16'd42470;
        223 : data<= 16'd42990;
        224 : data<= 16'd43524;
        225 : data<= 16'd44071;
        226 : data<= 16'd44631;
        227 : data<= 16'd45203;
        228 : data<= 16'd45788;
        229 : data<= 16'd46384;
        230 : data<= 16'd46992;
        231 : data<= 16'd47611;
        232 : data<= 16'd48241;
        233 : data<= 16'd48882;
        234 : data<= 16'd49532;
        235 : data<= 16'd50192;
        236 : data<= 16'd50862;
        237 : data<= 16'd51540;
        238 : data<= 16'd52226;
        239 : data<= 16'd52921;
        240 : data<= 16'd53623;
        241 : data<= 16'd54333;
        242 : data<= 16'd55049;
        243 : data<= 16'd55771;
        244 : data<= 16'd56500;
        245 : data<= 16'd57233;
        246 : data<= 16'd57972;
        247 : data<= 16'd58715;
        248 : data<= 16'd59463;
        249 : data<= 16'd60214;
        250 : data<= 16'd60968;
        251 : data<= 16'd61725;
        252 : data<= 16'd62485;
        253 : data<= 16'd63246;
        254 : data<= 16'd64009;
        255 : data<= 16'd64772;
    endcase

    
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/17 20:47:04
// Design Name: 
// Module Name: i2s_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module i2s_top(
    input clk,
    input rst_n,
    
    output i2s_clk,
    output i2s_din,
    output i2s_ws
    );

wire clk_6m;
reg [1:0] cnt;
wire clk_1p5m;
wire [15:0] sine_data;
reg [7:0] addr;
wire req_r;

assign i2s_clk=clk_1p5m;

clk_wiz_0 instance_name
(
.clk_out1(clk_6m),     // output clk_out1
.reset(~rst_n), // input reset
.clk_in1(clk));      // input clk_in1  

//clk_1p5m
always @(posedge clk_6m or negedge rst_n)
if(rst_n==0)
    cnt<=0;
else
    cnt<=cnt+1;

assign clk_1p5m=(cnt<=1)? 1:0;

i2s_drv u_i2s_dev(
    .clk_1p5m(clk_1p5m),
    .rst_n(rst_n),    
    .idata(sine_data),
    
    .req(req_r),
    .i2s_din(i2s_din),
    .i2s_ws(i2s_ws)
    );  

//addr
always @(posedge clk_1p5m or negedge rst_n)
if(rst_n==0)
    addr<=0;
else if(req_r)
    addr<=addr+1;
else
    addr<=addr;
    
rom_sine u_rom_sine(
    .clk(clk),
    .rst_n(rst_n),
    .addr(addr),
    .data(sine_data)
    );    
    
endmodule


`timescale 1ns/1ns
module test;
reg clk;
reg rst_n;

initial begin
    rst_n=0;
    #1000;
    rst_n=1;
end

initial begin
    clk=0;
    forever #10 clk=~clk;
end

i2s_top  u_i2s_top(
    .clk(clk),
    .rst_n(rst_n)
);
endmodule

z7-nano管脚约束

create_clock -period 20.000 [get_ports clk]

set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports clk]
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports rst_n]

set_property -dict {PACKAGE_PIN G15 IOSTANDARD LVCMOS33} [get_ports i2s_din]
set_property -dict {PACKAGE_PIN F17 IOSTANDARD LVCMOS33} [get_ports i2s_clk]
set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports i2s_ws]

测试效果

85bddc792e27d89aec127ef9509fe804 10553dcfc757899a925c4a780cafcc17

Clone this wiki locally