安德鲁

[原创].串行ADC TLC549读取实验,Verilog版本

0
阅读(2977)

原理图


时序图



笔记


源代码

顶层文件

module tlc_549_test(
  input  CLOCK_50, // 板载50MHz时钟 
  input  RST_N,
  //
  output ADC549_CLK,
  output ADC549_CS_N,
  input ADC549_DATA,
  //
  output [7:0] SEG7_SEG, // 七段数码管 段脚              
  output [7:0] SEG7_DIG  // 七段数码管 位脚 
);

wire [7:0] ad_data;
tlc549_driver tlc549_driver_inst(
    .CLOCK_50(CLOCK_50),
    .RST_N(RST_N),
    //
    .ad_enable(1'b1),
    .ad_data(ad_data),
    // 
    .nCS(ADC549_CS_N),
    .SCK(ADC549_CLK),
    .SDO(ADC549_DATA)
);

seg7x8_drive u0(
  .i_clk            (CLOCK_50),
  .i_rst_n          (RST_N),
  
  .i_turn_off       (8'b1111_1100), // 熄灭位[2进制]
  .i_dp             (8'b0000_0000), // 小数点位[2进制]
  .i_data           (ad_data), // 欲显数据[16进制]
  
  .o_seg            (SEG7_SEG),
  .o_dig            (SEG7_DIG)
);

endmodule

数码管驱动http://blog.chinaaet.com/detail/19652.html

TLC549驱动

module tlc549_driver
(
    input CLOCK_50,
    input RST_N,
    //
    input ad_enable,
    output reg [7:0] ad_data,
    // 
    output reg nCS,
    output reg SCK,
    input SDO
);

function integer log2(input integer n);
    integer i;
    for(i=0; 2**i <=n; i=i+1) log2=i+1;
endfunction

/**************************************
* 生成40ns的tick时钟
**************************************/
reg cnt_40ns;
always@(posedge CLOCK_50) cnt_40ns <= cnt_40ns + 1'b1;
wire tick_40ns = (cnt_40ns == 1'b1) ? 1 : 0;

/**************************************
* 根据tick时钟生成ad基准计数器
**************************************/
reg [log2(700):1] ad_ref_cnt; // [0,700]
always@(posedge CLOCK_50, negedge RST_N)
    if(!RST_N) ad_ref_cnt <= 0;
    else begin
        if(!ad_enable) ad_ref_cnt <= 0;
        else begin
            if(tick_40ns) begin
                if(ad_ref_cnt < 700) 
                    ad_ref_cnt <= ad_ref_cnt + 1'b1;
                else ad_ref_cnt <= 0;
            end
        end
    end
    
/**************************************
* 根据基准计数器生成串行信号
**************************************/
reg samping_flag; // 采样标志
always@(posedge CLOCK_50, negedge RST_N)
    if(!RST_N) begin
        nCS <= 1;
        SCK <= 0;
        samping_flag <= 0;
    end
    else begin
        if(tick_40ns) begin
            case(ad_ref_cnt)
                // 采样期
                36,58,80,102,124,146,168,190 : SCK <= 1;
                48,70,92,114,136,158,180,202 : SCK <= 0;          
                default : ; // 缺省不操作
            endcase
            case(ad_ref_cnt)
                0 : nCS <= 1;
                1 : nCS <= 0;
                // 转换期
                202: nCS <= 1;            
                default : ; // 缺省不操作
            endcase
            case(ad_ref_cnt)
                0 : samping_flag <= 0;
                // 采样期
                36 : samping_flag <= 1;
                // 转换期
                202: samping_flag <= 0;
                default : ; // 缺省不操作
            endcase
        end
    end
wire samping_end = (ad_ref_cnt == 202) ? 1 : 0; // 采样结束标志

/**************************************
* 根据串行信号读取串行样本数据
**************************************/
reg [7:0] sample_data;
always@(posedge SCK, negedge RST_N)
    if(!RST_N) sample_data <= {8{1'b0}};
    else begin
        if(SCK) begin
            if (samping_flag != 0) begin
                sample_data[7:1] <= sample_data[6:0];
                sample_data[0] <= SDO;
            end
        end
    end

always@(posedge CLOCK_50, negedge RST_N)
    if(!RST_N) ad_data <= {8{1'b0}};
    else begin
        if (samping_end)
            ad_data <= sample_data;
        else ad_data <= ad_data;
    end

endmodule

Signaltap硬件仿真



参考资料

http://focus.ti.com.cn/cn/lit/ds/symlink/tlc549.pdf