首页 > 技术文章 > DAC_TLV5618模块中产生任意偶数频率时钟SCLK

liujiahong 2020-04-11 15:48 原文

如果其他工程的外部器件需要用到一个SCLK,并且该外部器件的时序图可通过序列机实现(如DAC_TLV5618),则可以通过稍微改动来产生一个可变的时钟SCLK。
//
************************************************************ // DAC_TLV5618模块中的任意偶数频率分频 //************************************************************* module DAC_TLV5618( Clk, Rst_n, Start, DAC_data, // DAC_state Set_done, SCLK, CS, DIN ); input Clk; input Rst_n; input Start; // 模块使能信号 input [15:0] DAC_data; //控制器,控制字,高4位为控制字,低12位为数据位 output reg Set_done; //更新 DAC 完成标志,每次完成更新产生一个高电平脉冲,脉冲宽度为 1 个时钟周期 output reg SCLK; //TLV5618 的 SCLK 接口 output reg CS; //TLV5618 的 CS 接口 output reg DIN; //TLV5618 的 DIN 接口 // output DAC_state; //模块状态标识,低电平时为忙标志,高电平为空闲状态 parameter DIV_param = 2; //实际上这里的SCLK为CLK的4分频, DIV_param = 3,SCLK为CLK的6分频...... //reg define reg EN; //转换使能信号 reg SCLK2X; //2倍SCLK时钟频率 reg [7:0] DIV_cnt; //分频计数器 //reg [7:0] DIV_param; //可调分频参数 reg [5:0] SCLK2X_cnt; //对SCLK2X脉冲进行计数,用于计数产生序列机所需的脉冲数 //EN使能信号仅在数据传输时有效,传输完毕时无效 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) EN <= 1'b0; else if(Start) EN <= 1'b1; else if(Set_done) EN <= 1'b0; else EN <= EN; end //生成2倍SCLK使能时钟计数器 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) DIV_cnt <= 8'd0; else if(EN)begin if(DIV_cnt == (DIV_param - 1'b1)) DIV_cnt <= 8'd0; else DIV_cnt <= DIV_cnt + 1'b1; end else DIV_cnt <= 8'd0; end //生成SCLK2X时钟,高电平仅为一个clk周期的时间 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) SCLK2X <= 1'b0; else if(EN && (DIV_cnt == (DIV_param - 1'b1))) SCLK2X <= 1'b1; else SCLK2X <= 1'b0; end //对SCLK2X高电平进行计数,由DAC写入时序图得知,该序列机需要计数34个数 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) SCLK2X_cnt <= 6'd0; else if(EN) begin if(EN && SCLK2X) begin if(SCLK2X_cnt == 6'd33) SCLK2X_cnt <= 6'd0; else SCLK2X_cnt <= SCLK2X_cnt + 1'b1; end else SCLK2X_cnt <= SCLK2X_cnt; end else SCLK2X_cnt <= 6'd0; end //通过case语句,生成SCLK时钟频率,并且在对应的SCLK上升沿把数据送到DIN数据线上 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n)begin SCLK <= 1'b0; CS <= 1'b1; DIN <= 1'b1; Set_done <= 1'b0; end else if(!Set_done && SCLK2X)begin case(SCLK2X_cnt) 0 : begin SCLK <= 1'b1; DIN <= DAC_data[15] ; CS <= 1'b0; end 2 : begin SCLK <= 1'b1; DIN <= DAC_data[14] ; end 4 : begin SCLK <= 1'b1; DIN <= DAC_data[13] ; end 6 : begin SCLK <= 1'b1; DIN <= DAC_data[12] ; end 8 : begin SCLK <= 1'b1; DIN <= DAC_data[11] ; end 10 : begin SCLK <= 1'b1; DIN <= DAC_data[10] ; end 12 : begin SCLK <= 1'b1; DIN <= DAC_data[9] ; end 14 : begin SCLK <= 1'b1; DIN <= DAC_data[8] ; end 16 : begin SCLK <= 1'b1; DIN <= DAC_data[7] ; end 18 : begin SCLK <= 1'b1; DIN <= DAC_data[6] ; end 20 : begin SCLK <= 1'b1; DIN <= DAC_data[5] ; end 22 : begin SCLK <= 1'b1; DIN <= DAC_data[4] ; end 24 : begin SCLK <= 1'b1; DIN <= DAC_data[3] ; end 26 : begin SCLK <= 1'b1; DIN <= DAC_data[2] ; end 28 : begin SCLK <= 1'b1; DIN <= DAC_data[1] ; end 30 : begin SCLK <= 1'b1; DIN <= DAC_data[0] ; end 32 : begin SCLK <= 1'b1; end 1 ,3 , 5 , 7 , 9 , 11 , 13 , 15 , 17 , 19 , 21 , 23 , 25 , 27 , 29 , 31 : SCLK <= 1'b0; 33 : begin SCLK <= 1'b0; CS <= 1'b1; Set_done <= 1'b1; end default : ; endcase end else ; end endmodule

上述代码的仿代码:

//************************************************************
//                DAC_TLV5618_tb模块
//*************************************************************
`timescale  1ns/1ps
`define   clk_period  20

module DAC_TLV5618_tb;
reg          sys_clk;
reg          sys_rst_n;
reg          Start;
reg  [15:0]  DAC_data;

wire         SCLK;
wire         CS;
wire         Set_done;
wire         DIN;
//模块例化
DAC_TLV5618  #(.DIV_param(3)) DAC_TLV5618(          //仿真设置的是将CLK进行6分频得到时钟SCLK
    .Clk(sys_clk),
    .Rst_n(sys_rst_n),
    .Start(Start),
    .DAC_data(DAC_data),
    
//    .DAC_state(DAC_state),    
    .Set_done(Set_done),
    .SCLK(SCLK),
    .CS(CS),
    .DIN(DIN)
);    


initial    sys_clk = 1'b1;    

always #(`clk_period/2)  sys_clk = ~sys_clk;

initial begin
    sys_rst_n = 1'b0;
    Start = 1'b0;
    #10;
    sys_rst_n = 1'b1;
    Start = 1'b1;
    DAC_data = 16'd43690;
    #18_000;
    Start = 1'b0;
    #1000;
    Start = 1'b1;
    #18_000;
    Start = 1'b0;
    $stop;
   end

endmodule

仿真图(CLK6分频):

 

 

 

推荐阅读