fpga_feixiang 发表于 2020-3-2 12:36:13

FPGA 使用verilog 编写的AD tlc549 测试程序,数码管做显示

/*
**author : fengdawei
**data   : 2014/10/6
**description :
模块number_mod_module U5、smg_encoder_module U6、smg_scan_module U7、
row_scan_module U1、column_scan_module U2参照黑金数码管显示代码,用于显示
AD转换后的三位数值;
模块smg_check U4用于测试数码管正常显示;
模块ad_tlc549 U3用于AD处理,返回一个八位的数据,时序图具体参考TI官方资料
**此测试程序是为将ad数据存储到RAM和从RAM读走,测试ip核做准备。
*/
module experiment_ram(
clk,
rst,
//enable_ad,
ad_data,
row_scan_sig,
column_scan_sig,
ad_cs,
ad_clk
);


input clk;
input rst;


//input enable_ad;
input ad_data;


output row_scan_sig;
output column_scan_sig;
output ad_cs;
output ad_clk;






wire smg_display_data;
ad_tlc549 U3
(
.clk(clk),
.rst(rst),
//.enable_ad(enable_ad),
.ad_data(ad_data),
.ad_cs(ad_cs),
.ad_clk(ad_clk),
.digit_data(smg_display_data)
);
/**/
/*
//smg_check模块用于测试数码管
wire smg_display_data;
smg_check U4
(
.clk(clk),
.rst(rst),
.smg_display_data(smg_display_data)
);
*/
wire hundred_data;
wire ten_data;
wire one_data;
number_mod_module U5
(
.clk(clk),
.rst(rst),
.number_data(smg_display_data),
.hundred_data(hundred_data),
.ten_data(ten_data),
.one_data(one_data)
);


wire hundred_smg_data;
wire ten_smg_data;
wire one_smg_data;
smg_encoder_module U6
(
.clk(clk),
.rst(rst),
.hundred_data(hundred_data),
.ten_data(ten_data),
.one_data(one_data),
.hundred_smg_data(hundred_smg_data),
.ten_smg_data(ten_smg_data),
.one_smg_data(one_smg_data)
);


smg_scan_module U7
(
.clk(clk),
.rst(rst),
.hundred_smg_data(hundred_smg_data),
.ten_smg_data(ten_smg_data),//8'b1100_0000
.one_smg_data(one_smg_data),//8'b1100_0000
.row_scan_sig(row_scan_sig),
.column_scan_sig(column_scan_sig)
);
endmodule

/*
***The maximum I/O CLOCK input frequency of the TLC548 is 2.048 MHz, 
and the I/O CLOCK input frequency of theTLC549 is specified up to 1.1 MHz.
***the TLC548 and TLC549 provide an on-chip system clock that operates typically at 4 MHz
and requires no external components.
***Conversion Time...17 μs Max
***NOTES: A. The conversion cycle, which requires 36 internal system clock periods (17 μs maximum), 
is initiated with the eighth I/O clock pulse trailing edge after CS  goes low for the 
channel whose address exists in memory at the time.
B. The most significant bit (A7) is automatically placed on the DATA OUT bus after CS is 
brought low. The remaining seven bits (A6–A0) are clocked out on the first seven I/O 
clock falling edges. B7–B0 follows in the same manner.
**40 000 conversions per second for the TLC549
*/
module ad_tlc549(
clk,
rst,
//enable_ad,
ad_data,
ad_cs,
ad_clk,
digit_data
);


input clk;
input rst;
//input enable_ad;
input ad_data;


output ad_cs;
output ad_clk;
output digit_data;




//2^(11)=2048
reg clk_cnt;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
clk_cnt<=11'd0;
end
else if(clk_cnt>=11'd1320)
begin
clk_cnt<=11'b0;
end
else
begin
clk_cnt<=clk_cnt+1'b1;
end
end


/*
系统板50MHZ->一个时钟周期为0.02us
cs_high_data_exchange 17us->850个clk脉冲
每秒转换40000次,每次需要每次转换时间间隔25us,采样间隔 必须在25us以上
cs_low_data_read 1.4us+8个1MHZ的脉冲->1.4us+8us=9.4us ->70+400=470个clk脉冲
total clk pulse=1320个时钟周期
*/
wire cs_high_data_exchange;
wire cs_low_data_read;
reg rcs;
assign cs_high_data_exchange=(clk_cnt>=11'd0)  &&(clk_cnt<11'd850);
assign cs_low_data_read   =(clk_cnt>=11'd850)&&(clk_cnt<11'd1320);
assign cs_low_data_read1   =(clk_cnt>=11'd920)&&(clk_cnt<11'd1320);
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
rcs<=1'b1;
end
else
begin
if(cs_high_data_exchange)
rcs<=1'b1;
else
rcs<=1'b0;
end
end
assign ad_cs=rcs;


//2^6=64
//将系统时钟50MHz进行50分频成1MHz
reg div_cnt;
reg rad_clk;
reg count_read_data_pulse;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
div_cnt<=6'd0;
rad_clk<=1'b0;
count_read_data_pulse<=4'd0;
end
else if((cs_low_data_read1 )&&(count_read_data_pulse<8))
begin
div_cnt<=div_cnt+1'b1;
if(div_cnt<25)
begin
rad_clk<=1'b1;
end
else if(div_cnt>=49)
begin
count_read_data_pulse<=count_read_data_pulse+1'b1;
div_cnt<=6'd0;
end
else
rad_clk<=1'b0;
end
else if(!cs_low_data_read1)
begin
rad_clk<=1'b0;
count_read_data_pulse<=4'd0;
end
else
rad_clk<=1'b0;
end
assign ad_clk=rad_clk;


reg rad_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
rad_data<=8'd0;
end
else
begin
case (clk_cnt)

11'd920 :rad_data <= ad_data;
11'd970 :rad_data <= ad_data;
11'd1020:rad_data <= ad_data;
11'd1070:rad_data <= ad_data;
11'd1120:rad_data <= ad_data;
11'd1170:rad_data <= ad_data;
11'd1220:rad_data <= ad_data;
11'd1270:rad_data <= ad_data;
default:;


endcase
end
end
assign digit_data=rad_data;


endmodule



module smg_check(
clk,
rst,
smg_display_data
);
input clk;
input rst;
output smg_display_data;
//50MHz晶振:50000000为1s,10000000为0.2s
//parameter TIMES=26'd50000000;
parameter TIMES=24'd10000000;


reg clk_cnt;
always @ (posedge clk or negedge rst)
begin
if(!rst)
clk_cnt<=26'd0;
else if(clk_cnt>TIMES)
clk_cnt<=26'd0;
else
clk_cnt<=clk_cnt+1'b1;
end


reg rsmg_display_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
rsmg_display_data<=8'd0;
else if(rsmg_display_data>8'd255)
rsmg_display_data<=8'd0;
else if(clk_cnt==TIMES)
rsmg_display_data<=rsmg_display_data+1'b1;
end


assign smg_display_data=rsmg_display_data;


endmodule


module number_mod_module(
clk,
rst,
number_data,
hundred_data,
ten_data,
one_data
);
input clk;
input rst;
input number_data;
output hundred_data;
output ten_data;
output one_data;


reg rhundred_data;
reg rten_data;
reg rone_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
rhundred_data<=32'd0;
rten_data<=32'd0;
rone_data<=32'd0;
end
else 
begin
rhundred_data<=number_data/100;
rten_data<=number_data%100/10;
rone_data<=number_data%10;
end
end


assign hundred_data=rhundred_data;
assign ten_data=rten_data;
assign one_data=rone_data;


endmodule


module smg_encoder_module(
clk,
rst,
hundred_data,
ten_data,
one_data,
hundred_smg_data,
ten_smg_data,
one_smg_data
);
input clk;
input rst;
input hundred_data;
input ten_data;
input one_data;
output hundred_smg_data;
output ten_smg_data;
output one_smg_data;


parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, 
        _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010, 
_6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,
_9 = 8'b1001_0000;


reg rhundred_smg_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
rhundred_smg_data<=8'b1111_1111;
else
case(hundred_data)
4'd0:rhundred_smg_data<=_0;
4'd1:rhundred_smg_data<=_1;
4'd2:rhundred_smg_data<=_2;
4'd3:rhundred_smg_data<=_3;
4'd4:rhundred_smg_data<=_4;
4'd5:rhundred_smg_data<=_5;
4'd6:rhundred_smg_data<=_6;
4'd7:rhundred_smg_data<=_7;
4'd8:rhundred_smg_data<=_8;
4'd9:rhundred_smg_data<=_9;
endcase
end

reg rten_smg_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
rten_smg_data<=8'b1111_1111;
else
case(ten_data)
4'd0:rten_smg_data<=_0;
4'd1:rten_smg_data<=_1;
4'd2:rten_smg_data<=_2;
4'd3:rten_smg_data<=_3;
4'd4:rten_smg_data<=_4;
4'd5:rten_smg_data<=_5;
4'd6:rten_smg_data<=_6;
4'd7:rten_smg_data<=_7;
4'd8:rten_smg_data<=_8;
4'd9:rten_smg_data<=_9;
endcase
end

reg rone_smg_data;
always @ (posedge clk or negedge rst)
begin
if(!rst)
rone_smg_data<=8'b1111_1111;
else 
begin
case(one_data)
4'd0:rone_smg_data<=_0;
4'd1:rone_smg_data<=_1;
4'd2:rone_smg_data<=_2;
4'd3:rone_smg_data<=_3;
4'd4:rone_smg_data<=_4;
4'd5:rone_smg_data<=_5;
4'd6:rone_smg_data<=_6;
4'd7:rone_smg_data<=_7;
4'd8:rone_smg_data<=_8;
4'd9:rone_smg_data<=_9;
endcase
end
end
assign hundred_smg_data=rhundred_smg_data;
assign ten_smg_data=rten_smg_data;
assign one_smg_data=rone_smg_data;


endmodule



module smg_scan_module(
clk,
rst,
hundred_smg_data,
ten_smg_data,
one_smg_data,
row_scan_sig,
column_scan_sig
);
input clk;
input rst;
input hundred_smg_data;
input ten_smg_data;
input one_smg_data;
output row_scan_sig; //行 --段选
output column_scan_sig; //列 --位选


row_scan_module U1
(
.clk(clk),
.rst(rst),
.hundred_smg_data(hundred_smg_data),
.ten_smg_data(ten_smg_data),
.one_smg_data(one_smg_data),
.row_scan_sig(row_scan_sig)
);


column_scan_module U2
(
.clk(clk),
.rst(rst),
.column_scan_sig(column_scan_sig)
);


endmodule



module row_scan_module(
clk,
rst,
hundred_smg_data,
ten_smg_data,
one_smg_data,
row_scan_sig
);
input clk;
input rst;
input hundred_smg_data;
input ten_smg_data;
input one_smg_data;
output row_scan_sig;


parameter TIMES=18'd199_999;


reg count;
always @ (posedge clk or negedge rst)
begin
if(!rst)
count<=18'd0;
else if(count==TIMES)
count<=18'd0;
else
count<=count+1'b1;
end

reg t;
always @ (posedge clk or negedge rst)
begin
if(!rst)
t<=2'd0;
else if(t==2'd3)
t<=2'd0;
else if(count==TIMES)
t<=t+1'b1;
end


reg rdata;
always @ (posedge clk or negedge rst)
begin
if(!rst)
rdata<=8'd0;
else if(count==TIMES)
begin
case(t)
2'd0:rdata<=hundred_smg_data;
2'd1:rdata<=ten_smg_data;
2'd2:rdata<=one_smg_data;
default:;
endcase
end
end
assign row_scan_sig=rdata;


endmodule


module column_scan_module(
clk,
rst,
column_scan_sig
);

input clk;
input rst;
output column_scan_sig;


parameter TIMES=18'd199_999;


reg count;


always @ (posedge clk or negedge rst)
begin
if(!rst)
count<=18'd0;
else if(count==TIMES)
count<=18'd0;
else
count<=count+1'b1;
end


reg t;
always @ (posedge clk or negedge rst)
begin
if(!rst)
t<=2'd0;
else if(t==2'd3)
t<=2'd0;
else if(count==TIMES)
t<=t+1'b1;
end

reg rcolumn_scan_sig;
always @ (posedge clk or negedge rst)
begin
if(!rst)
begin
rcolumn_scan_sig<=2'b10;
end
else if(count==TIMES)
begin
case(t)
2'd0:rcolumn_scan_sig<=3'b011;
2'd1:rcolumn_scan_sig<=3'b101;
2'd2:rcolumn_scan_sig<=3'b110;
default:;
endcase
end
end
assign column_scan_sig=rcolumn_scan_sig;


endmodule

————————————————
页: [1]
查看完整版本: FPGA 使用verilog 编写的AD tlc549 测试程序,数码管做显示