安德鲁

[笔记].串型DAC TLC5620生成锯齿波、三角波实验,Verilog版本

0
阅读(18102)

原理图


时序图



思路


源代码

顶层模块

module tlc5620_test(
	    input  CLOCK_50, // 板载50MHz时钟
	    input  RST_N,
	    //
	    output ADC549_CLK,
	    output ADC549_CS_N,
	    input ADC549_DATA,
	    //
	    output DAC5620_CLK,
	    output DAC5620_DATA,
	    output DAC5620_LOAD,
	    //
	    output [7:0] SEG7_SEG, // 七段数码管 段脚             
	    output [7:0] SEG7_DIG  // 七段数码管 位脚
	);
	 
	function integer log2(input integer n);
	    integer i;
	    for(i=0; 2**i <=n; i=i+1) log2=i+1;
	endfunction
	 
	/**************************************
	* 生成20ms的tick时钟
	**************************************/
	reg [log2(1_1000_1000):1] cnt_20ms;
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) cnt_20ms <= 0;
	    else begin
	        if(cnt_20ms < 999_999)
	            cnt_20ms <= cnt_20ms + 1'b1;
	        else cnt_20ms <= 0;
	    end
	wire tick_20ms = (cnt_20ms == 999_999) ? 1 : 0;
	 
	 
	/**************************************
	* 锯齿波;接LED
	**************************************/
	reg [7:0] da0_data;
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) da0_data <= 0;
	    else if(tick_20ms) begin
	        if(da0_data < 255)
	            da0_data <= da0_data + 1'b1;
	        else da0_data <= 0;
	    end
	 
	/**************************************
	* 三角波;接LED
	**************************************/
	reg da1_highest_level_flag;
	reg [7:0] da1_data;
	 
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) begin
	        da1_data <= 0;
	        da1_highest_level_flag <= 0;
	    end else if(tick_20ms) begin
	        if(da1_data ==  255-1)
	            da1_highest_level_flag <= 1;
	        else if(da1_data == 0+1)
	            da1_highest_level_flag <= 0;
	         
	        if(da1_highest_level_flag)
	            da1_data <= da1_data - 1'b1;
	        else
	            da1_data <= da1_data + 1'b1;
	    end
	 
	wire [7:0] da2_data = 0;
	wire [7:0] da3_data = 0;
	        
	tlc5620_driver tlc5620_driver_inst
	(
	    .CLOCK_50(CLOCK_50),
	    .RST_N(RST_N),
	    //
	    .da_enable(1'b1),
	    .da_range(0), // 0, 1倍参考电压; 1, 2倍参考电压
	    .da0_data(da0_data), // 0~255
	    .da1_data(da1_data), // 0~255
	    .da2_data(da2_data), // 0~255
	    .da3_data(da3_data), // 0~255
	    //
	    .SCK(DAC5620_CLK),
	    .SDI(DAC5620_DATA),
	    .LOAD(DAC5620_LOAD)
	);
	 
	endmodule

tlc5620驱动

module tlc5620_driver
	(
	    input CLOCK_50,
	    input RST_N,
	    //
	    input da_enable,
	    input da_range, // 0, 1倍参考电压; 1, 2倍参考电压
	    input [7:0] da0_data, // 0~255
	    input [7:0] da1_data, // 0~255
	    input [7:0] da2_data, // 0~255
	    input [7:0] da3_data, // 0~255
	    //
	    output reg SCK,
	    output reg SDI,
	    output reg LOAD
	);
	 
	function integer log2(input integer n);
	    integer i;
	    for(i=0; 2**i <=n; i=i+1) log2=i+1;
	endfunction
	 
	/**************************************
	* 生成140ns的tick时钟
	**************************************/
	reg [log2(7):1]cnt_140ns;
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) cnt_140ns <= 0;
	    else begin
	        if(cnt_140ns < 6)
	            cnt_140ns <= cnt_140ns + 1'b1;
	        else cnt_140ns <= 0;
	    end
	wire tick_140ns = (cnt_140ns == 6) ? 1 : 0;
	 
	/**************************************
	* 根据tick时钟生成da基准计数器
	**************************************/
	reg [log2(48):1] da_ref_cnt; // [0,47]
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) da_ref_cnt <= 0;
	    else begin
	        if(!da_enable) da_ref_cnt <= 0;
	        else begin
	            if(tick_140ns) begin
	                if(da_ref_cnt < 47)
	                    da_ref_cnt <= da_ref_cnt + 1'b1;
	                else da_ref_cnt <= 0;
	            end
	        end
	    end
	wire tick_6720ns = (da_ref_cnt == 47) ? 1 : 0;
	 
	reg [1:0] da_sel_cnt;
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) da_sel_cnt <= 2'b0;
	    else if (tick_6720ns) begin
	        if(da_sel_cnt < 3)
	            da_sel_cnt <= da_sel_cnt + 1'b1;
	        else da_sel_cnt <= 2'b0;
	    end
	         
	/**************************************
	* 根据基准计数器生成串行信号
	**************************************/
	reg [7:0] da_data;
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) da_data <= 8'b0;
	    else begin
	        case(da_sel_cnt)
	            2'b00: da_data <= da0_data;
	            2'b01: da_data <= da1_data;
	            2'b10: da_data <= da2_data;
	            2'b11: da_data <= da3_data;
	        endcase
	    end
	 
	always@(posedge CLOCK_50, negedge RST_N)
	    if(!RST_N) begin
	        SCK <= 0;
	        SDI <= 0;
	        LOAD <= 0;
	    end
	    else begin
	        if(tick_140ns) begin
	            // 生成SCK信号
	            case(da_ref_cnt)
	                2,6,10,14,18,22,26,30,34,38,42: SCK <= 1;
	                4,8,12,16,20,24,28,32,36,40,44: SCK <= 0;
	                default : ; // 缺省不操作
	            endcase
	            // 生成LOAD信号
	            case(da_ref_cnt)
	                0: LOAD <= 1;
	                46: LOAD <= 0;
	                default : ; // 缺省不操作
	            endcase
	            // 送入串型数据
	            case(da_ref_cnt)
	                3,4: SDI <= da_sel_cnt[1];
	                7,8: SDI <= da_sel_cnt[0];
	                11,12: SDI <= da_range;
	                15,16: SDI <= da_data[7];
	                19,20: SDI <= da_data[6];
	                23,24: SDI <= da_data[5];
	                27,28: SDI <= da_data[4];
	                31,32: SDI <= da_data[3];
	                35,36: SDI <= da_data[2];
	                39,40: SDI <= da_data[1];
	                43,44: SDI <= da_data[0];
	                default : SDI <= 1'b1;
	            endcase
	        end
	    end
	 
	endmodule

Signaltap硬件仿真