原创 DAC芯片TLC5620的Verilog代码

2013-9-17 09:22 2239 8 8 分类: FPGA/CPLD

 

/**************************************************************************************************
** DAC11位数据输入说明:Bit[10:9] 通道选择00:CHA; 01:CHB; 10:CHC; 11:CHD
       Bit[8] RNG 0:参考电压到地 1:两倍参考电压到地
       Bit[7:0] DAC转换代码,范围0~255.
       输出电压Vo=REF*(CODE/256)*(1+RNG) 
**************************************************************************************************/

module       dac(
                        clk,
                        rst_n,
                        dac_clk,
                        dac_data,
                        dac_load,
                        sw1_n,sw2_n,sw3_n,sw4_n,
                        digit_o,
                        cs
                        );

input    clk;            // 输入时钟50MHz
input    rst_n;            // 复位
input    sw1_n,sw2_n,sw3_n,sw4_n;       // 按键
output    dac_clk;           // DAC时钟 MAX=1MHz
output    dac_data;           // DAC数据输出
output    dac_load;           // 加载信号
                 // 电路图中LDAC已经接地,因此略去
output [7:0] digit_o;           // 数码管输出
output [3:0]   cs;             // 数码管片选


parameter   DAC_Idle = 3'b001,        // 状态参数
     DAC_Send = 3'b010,
     DAC_Store = 3'b100;

//=================================================================================================
parameter                                                       // 字模
    MSK_0       = 8'hC0,       // '0'
    MSK_1       = 8'hF9,       // '1'
    MSK_2       = 8'hA4,       // '2'
    MSK_3       = 8'hB0,       // '3'
    MSK_4       = 8'h99,       // '4'
    MSK_5       = 8'h92,       // '5'
    MSK_6       = 8'h82,       // '6'
    MSK_7       = 8'hF8,       // '7'
    MSK_8       = 8'h80,       // '8'
    MSK_9       = 8'h90,       // '9'
    MSK_A       = 8'h88,       // 'A'
    MSK_B       = 8'h83,       // 'B'
    MSK_C       = 8'hC6,       // 'C'
    MSK_D       = 8'hA1,       // 'D'
    MSK_E       = 8'h86,       // 'E'
    MSK_F       = 8'h8E;       // 'F'
//=================================================================================================
/**************************************************************************************************
** 按键部分
**************************************************************************************************/
reg [3:0] key_rst;                                             // 保存按键前一个状态
always @(posedge clk or negedge rst_n)
     if (!rst_n)
      key_rst <= 4'b1111;
   else key_rst <= {sw4_n,sw3_n,sw2_n,sw1_n};

reg[3:0] key_rst_r;                                        // 保存按键下一个状态
always @(posedge clk or negedge rst_n)
     if (!rst_n)
        key_rst_r <= 4'b1111;
   else key_rst_r <= key_rst;
  
wire[3:0] key_val = key_rst_r & (~key_rst);              // 检测是否有1到0跳变

reg[19:0] cnt;                                             // 计数器
always @(posedge clk or negedge rst_n)
     if (!rst_n)
      cnt <= 20'd0;
   else if (key_val)                                      // 有按键按下(由1变为0)计数器开始计时 20ms
      cnt <= 20'd0;
   else
         cnt <= cnt + 1'b1;
   
// 去抖动后的按键检测,仍然用两级寄存器
    reg[3:0] low_sw;
always @(posedge clk or negedge rst_n)
     if (!rst_n)
      low_sw <= 4'b1111;
   else if (cnt == 20'hfffff)                            // 20ms后的按键状态锁存到low_sw中
            low_sw <= {sw4_n,sw3_n,sw2_n,sw1_n};

    reg[3:0] low_sw_r;
    always @(posedge clk or negedge rst_n)
     if (!rst_n)
            low_sw_r <= 4'b1111;
   else
      low_sw_r <= low_sw;

wire[3:0] led_ctrl = low_sw_r & (~low_sw);

reg [10:0] rData;
always @(posedge clk or negedge rst_n)
     if (!rst_n)                                            
     rData <= 11'd255;
   else begin                                                 
    if (led_ctrl[0] == 1)         // S1键按下
      rData[10:9] <= rData[10:9] + 1'b1;     // 通道切换
    if (led_ctrl[1] == 1)         // S2键按下
      rData[8] <= ~rData[8];        // RNG位变化
    if (led_ctrl[2] == 1)         // S3键按下
      rData[7:0] <= rData[7:0] + 8'd8;              // CODE变化
   end
/*************************************************************************************************/

/**************************************************************************************************
** DAC控制部分
**************************************************************************************************/
reg [5:0]   div_cnt;           // 分频计数器 64分频
reg     div_clk;           // 分频时钟 注意不是DAC输入时钟
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
     div_cnt <= 6'd0;
div_clk <= 1'bz;
end
else begin 
         div_cnt <= div_cnt + 1'b1;
         if (div_cnt == 6'd63)
            div_clk <= 1'b1;
   else
      div_clk <= 1'b0;
   end 
/*************************************************************************************************/
reg [2:0]   current_state,next_state;
reg     rDac_load;
reg     bit_cnt_rst;          // 位计数器复位信号
wire    dat_send_done;
always @(posedge clk or negedge rst_n)        // 时序进程
if (!rst_n)
     current_state <= DAC_Idle;
else 
     current_state <= next_state;

always @(current_state or div_clk or dat_send_done) begin   // 组合进程
rDac_load   <= 1'b1;
bit_cnt_rst <= 1'b0;
next_state <= DAC_Idle;
case (current_state)
    DAC_Idle: begin
   bit_cnt_rst <= 1'b1;
   next_state <= DAC_Send;             // 空闲时直接进入send状态
end 

DAC_Send: begin
   if (dat_send_done)           // 数据发送完成
      next_state <= DAC_Store;
   else
      next_state <= DAC_Send;
end

DAC_Store: begin
   bit_cnt_rst <= 1'b1;
   rDac_load   <= 1'b0;           // LOAD变低进行锁存
   if (div_clk)
      next_state <= DAC_Idle;
   else
      next_state <= DAC_Store;
end

endcase
end
/*************************************************************************************************/
reg [4:0] bit_cnt;            // 位计数器 对div_clk计数
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
     bit_cnt <= 5'd0;
else if (bit_cnt_rst)
     bit_cnt <= 5'd0;
else if (div_clk)
     bit_cnt <= bit_cnt + 1'b1;
end

assign dat_send_done = (bit_cnt == 5'd24);
/*************************************************************************************************/
reg   rDac_data;
always @(bit_cnt[4:1] or rData) begin
case (bit_cnt[4:1])             // 从高到低发送11位数据
    4'd1 : rDac_data <= rData[10];
    4'd2 : rDac_data <= rData[9];
    4'd3 : rDac_data <= rData[8];
   4'd4 : rDac_data <= rData[7];
   4'd5 : rDac_data <= rData[6];
   4'd6 : rDac_data <= rData[5];
    4'd7 : rDac_data <= rData[4];
   4'd8 : rDac_data <= rData[3];
   4'd9 : rDac_data <= rData[2];
    4'd10: rDac_data <= rData[1];
    4'd11: rDac_data <= rData[0];
   default : rDac_data <= 1'b0;
endcase
end
/*************************************************************************************************/
reg   rDac_clk;
always @(bit_cnt) begin            // DAC_CLK输出时钟的产生 period=2560ns
if ((bit_cnt >= 2) && (bit_cnt <24))
     rDac_clk <= ~bit_cnt[0];          // 在时钟下降沿数据要有效
else
     rDac_clk <= 1'b0;
end
/*************************************************************************************************/
assign dac_clk = rDac_clk;
assign dac_data = rDac_data;
assign dac_load = rDac_load;
/**************************************************************************************************/

/**************************************************************************************************
** 数码管显示部分
** 说明:数码管1显示通道 数码管2显示RNG值
**          数码管3和4显示CODE值
**************************************************************************************************/
reg    [3:0]    cs;                                             // 片选信号
reg    [16:0]   cnt2;                                           // 计数寄存器2,确定扫描间隔
reg    [3:0]    submsk;                                         // 保存要显示的数据

always @(posedge clk or negedge rst_n)
if (!rst_n)
      begin
     cnt2 <= 17'd0;                                        // 计数器2置零
   cs    <= 4'b0111;
   end
else begin
          cnt2 <= cnt2 + 1'b1;                                // 计数器2开始计数
          if (cnt2 == 17'd0)                                   // 溢出了,又从0开始   
        begin
       if (cs == 4'b0111)
      begin
            cs      <= 4'b1110;                          // 选择第四个数码管
      submsk <= rData[3:0];                       // 显示CODE低4位
      end 
          else if (cs == 4'b1110)
            begin      
            cs      <= 4'b1101;                          // 选择第三个数码管
         submsk <= rData[7:4];         // 显示CODE高4位
         end
                else if (cs == 4'b1101)    
                  begin
        cs     <= 4'b1011;        // 选择第二个数码管
      submsk <= {3'b000,rData[8]};     // 显示RNG值
      end
     else if (cs == 4'b1011) 
      begin
        cs      <= 4'b0111;            // 选择第一个数码管
        submsk <= {2'b00,rData[10:9]} + 1'b1;   // 显示通道
      end
     end
   end

reg    [7:0]    digit_o;                                        // 数码管输出寄存器
always @(submsk)
case (submsk) 
    4'h0:       digit_o <= MSK_0;
    4'h1:       digit_o <= MSK_1;
    4'h2:       digit_o <= MSK_2;
    4'h3:       digit_o <= MSK_3;
    4'h4:       digit_o <= MSK_4;
    4'h5:       digit_o <= MSK_5;
    4'h6:       digit_o <= MSK_6;
    4'h7:       digit_o <= MSK_7;
    4'h8:       digit_o <= MSK_8;
    4'h9:       digit_o <= MSK_9;
    4'hA:       digit_o <= MSK_A;
    4'hB:       digit_o <= MSK_B;
    4'hC:       digit_o <= MSK_C;
    4'hD:       digit_o <= MSK_D;
    4'hE:       digit_o <= MSK_E;
    4'hF:       digit_o <= MSK_F;
    default:    digit_o <= MSK_8;
    endcase
endmodule

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
8
关闭 站长推荐上一条 /3 下一条