小梅哥线性序列机SPI接口和ADC控制逻辑设计


 

 

代码:

module adc128s102_driver(
    clk_i,
    reset_n_i,
    addr_i,
    conv_go_i,
    dout_i,
    data_o,
    conv_done_o,
    cs_n_o,
    sclk_o,
    din_o
    );
    
    input [2:0] addr_i;
    input conv_go_i,dout_i,clk_i,reset_n_i;
    output conv_done_o,cs_n_o,sclk_o,din_o;
    output [11:0] data_o;
    
    // conv_go_i
    reg conv_en;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i) 
            conv_en <= 0;
        else if(conv_go_i)
            conv_en <= 1;
 
            
    // sclk_o 翻转间隔计数器
    parameter FREQUENCY = 50_000_000; // Hz
    parameter SCLK_FREQUENCY = 12_500_000;  // Hz
    parameter SCLK_TURN_INTERVAL = FREQUENCY/SCLK_FREQUENCY/2;  
    reg [31:0] sclk_turn_interval_cnt;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i) 
            sclk_turn_interval_cnt <= 0;
        else if(conv_en)begin
            if(sclk_turn_interval_cnt == (SCLK_TURN_INTERVAL - 1))
                sclk_turn_interval_cnt <= 0; 
            else 
                sclk_turn_interval_cnt <= sclk_turn_interval_cnt + 1;
        end else
            sclk_turn_interval_cnt <= 0;
    
    // sclk_o 翻转次数计数器       
    reg [5:0] sclk_turn_cnt;
    parameter INTERVAL_NUMBER = 35;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i) 
            sclk_turn_cnt <= 0;
        else if(sclk_turn_interval_cnt == (SCLK_TURN_INTERVAL - 1)) 
            if(sclk_turn_cnt == (INTERVAL_NUMBER - 1))
                sclk_turn_cnt <= 0;
            else
                sclk_turn_cnt <= sclk_turn_cnt + 1; 
    
    // 序列机
    reg cs_n_o,sclk_o,din_o;
    reg [11:0] r_data_o;
    
    always@(*) 
        if(!reset_n_i) begin 
            r_data_o <= 0;
            sclk_o <= 1;
            din_o <= 0;
        end else begin
            case(sclk_turn_cnt)
                0 :  begin cs_n_o <= 1; sclk_o <= 1;end
                1 :  begin cs_n_o <= 0;end
                2 :  begin sclk_o <= 0;end
                3 :  begin sclk_o <= 1;end
                4 :  begin sclk_o <= 0;end
                5 :  begin sclk_o <= 1;end
                6 :  begin sclk_o <= 0; din_o <= addr_i[2];end
                7 :  begin sclk_o <= 1;end
                8 :  begin sclk_o <= 0; din_o <= addr_i[1];end
                9 :  begin sclk_o <= 1;end
                10:  begin sclk_o <= 0; din_o <= addr_i[0];end
                11:  begin sclk_o <= 1; r_data_o[11]<= dout_i;end
                12:  begin sclk_o <= 0;din_o <= 0;end
                13:  begin sclk_o <= 1;r_data_o[10] <= dout_i;end
                14:  begin sclk_o <= 0; end
                15:  begin sclk_o <= 1; r_data_o[9] <= dout_i;end
                16:  begin sclk_o <= 0; end
                17:  begin sclk_o <= 1; r_data_o[8] <= dout_i;end
                18:  begin sclk_o <= 0; end
                19:  begin sclk_o <= 1; r_data_o[7] <= dout_i;end
                20:  begin sclk_o <= 0; end
                21:  begin sclk_o <= 1; r_data_o[6] <= dout_i;end
                22:  begin sclk_o <= 0; end
                23:  begin sclk_o <= 1; r_data_o[5] <= dout_i;end
                24:  begin sclk_o <= 0; end
                25:  begin sclk_o <= 1; r_data_o[4] <= dout_i;end
                26:  begin sclk_o <= 0; end
                27:  begin sclk_o <= 1; r_data_o[3] <= dout_i;end
                28:  begin sclk_o <= 0; end
                29:  begin sclk_o <= 1; r_data_o[2] <= dout_i;end
                30:  begin sclk_o <= 0; end
                31:  begin sclk_o <= 1; r_data_o[1] <= dout_i;end
                32:  begin sclk_o <= 0; end
                33:  begin sclk_o <= 1; r_data_o[0] <= dout_i;end
                34:  begin cs_n_o <= 1; end
            endcase
        end 
        
    // conv_done_o 与 data_o
    reg [11:0] data_o;
    reg conv_done_o;
    always@(posedge clk_i or negedge reset_n_i)
        if(!reset_n_i) begin
            data_o <= 0;
            conv_done_o <= 0;
        end else if((sclk_turn_cnt == INTERVAL_NUMBER - 1) && (sclk_turn_interval_cnt == (SCLK_TURN_INTERVAL - 1)))begin 
            conv_done_o <= 1;
            data_o <= r_data_o;
            conv_en <= 0;
        end else 
            conv_done_o <= 0;
       
endmodule

仿真:

`timescale 1ns / 1ps
 
module adc128s102_driver_tb();
 
    reg [2:0] u_addr_i;
    reg u_conv_go_i,u_dout_i,u_clk_i,u_reset_n_i;
    wire u_conv_done_o,u_cs_n_o,u_sclk_o,u_din_o;
    wire [11:0] u_data_o;
    
    adc128s102_driver U_adc128s102_driver_0(
        .clk_i(u_clk_i),
        .reset_n_i(u_reset_n_i),
        .addr_i(u_addr_i),
        .conv_go_i(u_conv_go_i),
        .dout_i(u_dout_i),
        .data_o(u_data_o),
        .conv_done_o(u_conv_done_o),
        .cs_n_o(u_cs_n_o),
        .sclk_o(u_sclk_o),
        .din_o(u_din_o)
    );
 
    initial u_clk_i = 1;
    always #10 u_clk_i = ~u_clk_i; 
 
    initial begin
        u_reset_n_i = 0;
        u_addr_i = 3'b101;
        u_dout_i = 0;
        #201;
        u_reset_n_i = 1;
        u_conv_go_i = 1;
        #40;
        u_conv_go_i = 0;
        #300;
        #80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        u_dout_i = 1;#80;
        u_dout_i = 0;#80;
        
        u_dout_i = 0;
        #1_000;
        u_conv_go_i = 0;
        #1_000;
        $stop;
    end
    
endmodule

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值