/**************************************************************************************************
** 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
文章评论(0条评论)
登录后参与讨论