FPGA实现的数模转换
D/A 转换器在电子系统中应用极为广泛,除了在微机系统中将数字量转化为模拟量典型应用之外,还常用于波形生成、各种数字式的可编程应用。
数字信号通常要用二进制的数来表示数的大小,按照“位权”的定义原则,每一位二进制代码根据其在数据中的位置不同,分别表示不同的值,为了将数字量转换成模拟量,必须将每一位的代码按其权的大小转换成相应的模拟量,然后将这些模拟量相加,得到与数字量成正比的总模拟量,这就是D/A转换的基本思路。
在D/A转换过程中,输入的数字信号是二进制编码。通过转换,将该编码按每位权的大小换算成相应的模拟量,然后将代表各位数字的模拟量相加,得到的和就是与输入的数字信号成正比的模拟量。
以下是通过调用两个模块实现数模转换:
顶层模块:
module DA(clk, rst_n, load, ldac, da_clk, da_data, sel, seg);
input clk;
input rst_n;
output load;
output ldac;
output da_clk; //最大1MHz
output da_data;
output [2:0] sel;
output [7:0] seg;
wire [12:0] data;
DA_driver DA_driver_inst(
.clk (clk),
.rst_n (rst_n),
.load (load),
.ldac (ldac),
.da_clk (da_clk),
.da_data (da_data),
.data (data)
);
seven_tube_driver seven_tube_driver_inst(
.clk (clk),
.rst_n (rst_n),
.data (data),
.sel (sel),
.seg (seg)
);
endmodule
DA_drive模块:data的每一位显示在相应的数码管上,在da-clk的上升沿给da_data赋值,赋值显示在程序中,data赋值之后给数码管现实
module DA_driver(clk, rst_n, load, ldac, da_clk, da_data, data);
input clk;
input rst_n;
output reg load;
output ldac;
output reg da_clk;
output reg da_data;
output [12:0] data;
parameter code = 8'd150;
parameter RNG = 1;
parameter selet = 2'b00;
parameter t = 550;
reg [9:0] cnt;
assign ldac = 1'b0;
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
cnt <= 10'd0;
else if(cnt == t - 1)
cnt <= 10'd0;
else
cnt <= cnt + 1'b1;
end
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
load <= 1'b1;
da_clk <= 1'b0;
da_data <= 1'b0;
end
else
case(cnt)
0 : begin
da_clk <= 1'b1;
da_data <= selet[1];
end
24 : da_clk <= 1'b0;
49 : begin
da_clk <= 1'b1;
da_data <= selet[0];
end
74 : da_clk <= 1'b0;
99 : begin
da_clk <= 1'b1;
da_data <= RNG;
end
124 : da_clk <= 1'b0;
149 : begin
da_clk <= 1'b1;
da_data <= code[7];
end
174 : da_clk <= 1'b0;
199 : begin
da_clk <= 1'b1;
da_data <= code[6];
end
224 : da_clk <= 1'b0;
249 : begin
da_clk <= 1'b1;
da_data <= code[5];
end
274 : da_clk <= 1'b0;
299 : begin
da_clk <= 1'b1;
da_data <= code[4];
end
324 : da_clk <= 1'b0;
349 : begin
da_clk <= 1'b1;
da_data <= code[3];
end
374 : da_clk <= 1'b0;
399 : begin
da_clk <= 1'b1;
da_data <= code[2];
end
424 : da_clk <= 1'b0;
449 : begin
da_clk <= 1'b1;
da_data <= code[1];
end
474 : da_clk <= 1'b0;
499 : begin
da_clk <= 1'b1;
da_data <= code[0];
end
524 : da_clk <= 1'b0;
529 : load <= 1'b0;
544 : load <= 1'b1;
549 : ; 550做一个循环
default: ;
endcase
end
assign data = 2500 * code / 256 * (1 + RNG);
endmodule
module seven_tube_driver模块:数码管控制模块
module seven_tube_driver(clk, rst_n, data, sel, seg);
input clk;
input rst_n;
input [12:0] data;
output reg [2:0] sel;
output [7:0] seg;
parameter t = 50_000; 五十分频的时钟
reg [15:0] cnt;
reg flag;
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt <= 16'd0;
flag <= 1'b0;
end
else if(cnt == t - 1)
begin
cnt <= 16'd0;
flag <= 1'b1;
end
else
begin
cnt <= cnt + 1'b1;
flag <= 1'b0;
end
end
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
sel <= 3'b010;
else if(flag)
begin
if(sel == 3'b101)
sel <= 3'b010;
else
sel <= sel + 1'b1;
end
else
sel <= sel;
end
reg [3:0] show_data;
always @ (*)
begin
case(sel)
// 3'b000 : show_data = data/100000;
// 3'b001 : show_data = data/10000%10;
3'b010 : show_data = data/1000;
3'b011 : show_data = data/100%10;
3'b100 : show_data = data/10%10;
3'b101 : show_data = data%10;
default : show_data = 0;
endcase
end
reg [7:0] seg_r;
always @ (*)
begin
case(show_data)
0 : seg_r = 8'b1100_0000;
1 : seg_r = 8'b1111_1001;
2 : seg_r = 8'b1010_0100;
3 : seg_r = 8'b1011_0000;
4 : seg_r = 8'b1001_1001;
5 : seg_r = 8'b1001_0010;
6 : seg_r = 8'b1000_0010;
7 : seg_r = 8'b1111_1000;
8 : seg_r = 8'b1000_0000;
9 : seg_r = 8'b1001_0000;
default : seg_r = 8'b1111_1111;
endcase
end
assign seg = (sel == 3'b010) ? seg_r & 8'b0111_1111 : seg_r;
endmodule
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删