├── README.md ├── tft_display.v ├── data_process.v ├── tft_driver.v └── ad7928.v /README.md: -------------------------------------------------------------------------------- 1 | # 基于FPGA的数字示波器 2 | #### 项目介绍 3 | 基于FPGA的双通道2M/12bit示波器。通过800*480VGA显示器显示。 4 | 5 | * 首次更新 2018.12.29 6 | * 基于FPGA的数字示波器; 7 | * 2MSPS/12bit ADC; 8 | * 800*480VGA显示器。 9 | 10 | -------------------------------------------------------------------------------- /tft_display.v: -------------------------------------------------------------------------------- 1 | module tft_display( 2 | input clk, 3 | input rst_n, 4 | 5 | input [10:0] hcount, 6 | input [10:0] vcount, 7 | 8 | input q, 9 | 10 | output [15:0] vga_data, 11 | 12 | output [18:0] address 13 | ); 14 | 15 | 16 | 17 | `define RED 24'hff0000 18 | `define GREEN 24'h00ff00 19 | `define BLUE 24'h0000ff 20 | `define WHITE 24'hffffff 21 | `define BLACK 24'h000000 22 | `define YELLOW 24'hffff00 23 | `define CYAN 24'hff00ff 24 | `define ROYAL 24'h00ffff 25 | 26 | 27 | assign address = hcount[10:0] + vcount[10:0]*800; 28 | assign vga_data = {q,q,q,q,q,q,q,q,q,q,q,q,q,q,q,q}; 29 | 30 | 31 | endmodule -------------------------------------------------------------------------------- /data_process.v: -------------------------------------------------------------------------------- 1 | module data_process 2 | ( 3 | input clk, 4 | input clk_adc_dout_0, 5 | input clk_data_rst_n, 6 | input rst_n, 7 | output clk_data_process, 8 | 9 | input [11:0] dout_0, 10 | 11 | output reg write_enable=0, 12 | 13 | output reg data_rst_n=0, 14 | output [18:0] z 15 | 16 | 17 | ); 18 | 19 | reg [19:0] cnt; 20 | 21 | reg [19:0] address; 22 | 23 | wire data_rst_n_2; 24 | 25 | assign data_rst_n_2=data_rst_n & write_enable; 26 | 27 | assign clk_data_process = data_rst_n ? (data_rst_n_2?clk_data_rst_n:clk):clk_adc_dout_0; 28 | 29 | always@(posedge clk_data_process or negedge rst_n) 30 | begin 31 | if(!rst_n) 32 | cnt<=20'b0; 33 | 34 | else if(cnt==20'd768799) 35 | cnt<=20'b0; 36 | 37 | else 38 | cnt<=cnt+1'b1; 39 | 40 | end 41 | 42 | always@(posedge clk_data_process or negedge rst_n) 43 | begin 44 | if(!rst_n) 45 | address<=19'b0; 46 | 47 | else if(cnt==20'd383999) 48 | address<=19'b0; 49 | 50 | else if(cnt>=20'd384799) 51 | address<=19'b0; 52 | 53 | else 54 | address<=address+1'b1; 55 | 56 | end 57 | 58 | always@(posedge clk_data_process or negedge rst_n) 59 | begin 60 | if(!rst_n) 61 | data_rst_n<=1'b0; 62 | 63 | else if(cnt>=20'd383999&&cnt<=20'd384799) 64 | data_rst_n<=1'b0; 65 | 66 | else 67 | data_rst_n<=1'b1; 68 | 69 | end 70 | 71 | always@(posedge clk_data_process or negedge rst_n) 72 | begin 73 | if(!rst_n) 74 | write_enable<=1'b0; 75 | 76 | else if(cnt<=19'd384799) 77 | write_enable<=1'b1; 78 | 79 | else 80 | write_enable<=1'b0; 81 | 82 | end 83 | 84 | assign z = (data_rst_n )?(address ): ( 17'd101600 + address - dout_0[11:5]*800); 85 | 86 | endmodule 87 | 88 | -------------------------------------------------------------------------------- /tft_driver.v: -------------------------------------------------------------------------------- 1 | module tft_driver( 2 | input clk, //33.3M 3 | input rst_n, 4 | input [15:0] data_in, //待显示数据 5 | 6 | output [10:0] hcount, 7 | output [10:0] vcount, 8 | output [15:0] tft_rgb, //TFT数据输出 9 | output tft_hsync, 10 | output tft_vsync, 11 | output tft_clk, 12 | output tft_blank_n, 13 | output tft_pwm 14 | 15 | ); 16 | 17 | 18 | 19 | reg [10:0] hcount_r; //TFT行扫描计数器 20 | reg [10:0] vcount_r; //TFT场扫描计数器 21 | 22 | wire hcount_ov; 23 | wire vcount_ov; 24 | wire dat_act; //有效显示区标定 25 | 26 | //TFT行、场扫描时序参数表 27 | parameter 28 | tft_hsync_end =11'd1, 29 | hdat_begin =11'd46, 30 | hdat_end =11'd846, 31 | hpixel_end =11'd1056, 32 | tft_vsync_end =11'd1, 33 | vdat_begin =11'd24, 34 | vdat_end =11'd504, 35 | vline_end =11'd524; 36 | 37 | assign hcount=dat_act ? (hcount_r-hdat_begin):11'd0; 38 | assign vcount=dat_act ? (vcount_r-vdat_begin):11'd0; 39 | 40 | assign tft_clk=clk; 41 | assign tft_blank_n=dat_act; 42 | assign tft_pwm=rst_n; 43 | 44 | //TFT驱动部分 45 | //行扫扫描 46 | always@(posedge clk or negedge rst_n) 47 | if(!rst_n) 48 | hcount_r<=11'd0; 49 | else if(hcount_ov) 50 | hcount_r<=11'd0; 51 | else 52 | hcount_r<=hcount_r+11'd1; 53 | 54 | assign hcount_ov=(hcount_r==hpixel_end); 55 | 56 | //场扫描 57 | always@(posedge clk or negedge rst_n) 58 | if(!rst_n) 59 | vcount_r<=11'd0; 60 | else if(hcount_ov) 61 | begin 62 | if(vcount_ov) 63 | vcount_r<=11'd0; 64 | else 65 | vcount_r<=vcount_r+11'd1; 66 | end 67 | else 68 | vcount_r<=vcount_r; 69 | 70 | assign vcount_ov=(vcount_r==vline_end); 71 | 72 | //数据、同频信号输出 73 | assign dat_act=((hcount_r>=hdat_begin)&&(hcount_r=vdat_begin)&&(vcount_rtft_hsync_end); 76 | assign tft_vsync=(vcount_r>tft_vsync_end); 77 | assign tft_rgb=(dat_act)?data_in:16'h0000; 78 | 79 | endmodule -------------------------------------------------------------------------------- /ad7928.v: -------------------------------------------------------------------------------- 1 | module AD7928( 2 | input clk, 3 | input rst_n, 4 | output reg [11:0] dout_0, //并行输出 5 | output reg [11:0] dout_1, 6 | output reg [11:0] dout_2, 7 | output reg [11:0] dout_3, 8 | output reg [11:0] dout_4, 9 | output reg [11:0] dout_5, 10 | output reg [11:0] dout_6, 11 | output reg [11:0] dout_7, 12 | output reg [7:0] dout_vld, //数据有效信号,1为有效 13 | 14 | 15 | 16 | input adc_dout, //adc输出(串行) 17 | output reg adc_din, //adc输入 18 | output reg adc_sclk, //adc时钟 19 | output reg adc_cs_n //adc片选信号 20 | ); 21 | 22 | 23 | 24 | //--------------------------------- 25 | //主计数器 26 | reg [5:0] cnt0; 27 | always@(posedge clk or negedge rst_n) 28 | begin 29 | if(!rst_n) 30 | begin 31 | cnt0 <= 0; 32 | end 33 | 34 | else if(cnt0 == 37) 35 | begin 36 | cnt0 <= 0; 37 | end 38 | 39 | else 40 | cnt0 <= cnt0 + 1'b1; 41 | end 42 | //--------------------------------- 43 | 44 | 45 | 46 | //---------------------------------- 47 | //CS信号 48 | always@(posedge clk or negedge rst_n) 49 | begin 50 | if(!rst_n) 51 | begin 52 | adc_cs_n <= 1; 53 | end 54 | 55 | else if(cnt0 == 2) 56 | begin 57 | adc_cs_n <= 0; 58 | end 59 | 60 | else if(cnt0 == 35) 61 | begin 62 | adc_cs_n <= 1; 63 | end 64 | 65 | end 66 | //---------------------------------- 67 | 68 | 69 | //---------------------------------- 70 | //SCLK信号 71 | always@(posedge clk or negedge rst_n) 72 | begin 73 | if(!rst_n) 74 | begin 75 | adc_sclk <= 1; 76 | end 77 | 78 | else if(cnt0==3 | cnt0==5 | cnt0==7 | cnt0==9 | cnt0==11 | cnt0==13 | cnt0==15 | cnt0==17 | cnt0==19 | cnt0==21 | cnt0==23 | cnt0==25 | cnt0==27 | cnt0==29 | cnt0==31 | cnt0==33) 79 | begin 80 | adc_sclk <= 0; 81 | end 82 | 83 | else if(cnt0==4 | cnt0==6 | cnt0==8 | cnt0==10 | cnt0==12 | cnt0==14 | cnt0==16 | cnt0==18 | cnt0==20 | cnt0==22 | cnt0==24 | cnt0==26 | cnt0==28 | cnt0==30 | cnt0==32 | cnt0==34) 84 | begin 85 | adc_sclk <= 1; 86 | end 87 | end 88 | //---------------------------------- 89 | 90 | 91 | //--------------------------------------------- 92 | //地址计数器 93 | reg [2:0] cnt_address; 94 | 95 | reg cs_n; 96 | reg cs_n_wrsigrise; 97 | //检测adc_cs_n上升沿 98 | always@(posedge clk) 99 | begin 100 | cs_n <= adc_cs_n; 101 | cs_n_wrsigrise <= (!cs_n) & adc_cs_n; 102 | end 103 | 104 | 105 | always@(posedge clk or negedge rst_n) 106 | begin 107 | if(!rst_n) 108 | begin 109 | cnt_address <= 0; 110 | end 111 | 112 | else if(cs_n_wrsigrise) 113 | if(cnt_address==3'b001)//3'b111 114 | begin 115 | cnt_address <= 0; 116 | end 117 | 118 | else 119 | begin 120 | cnt_address <= cnt_address + 1; 121 | end 122 | end 123 | //--------------------------------------------- 124 | 125 | 126 | //--------------------------------------------- 127 | //串行输出给adc 128 | parameter WRITE = 1'b1; 129 | parameter PM = 2'b11; 130 | parameter SEQ = 1'b0; 131 | parameter SHADOW = 1'b0; 132 | parameter RANGE = 1'b0; 133 | parameter CODING = 1'b1; 134 | 135 | wire [15:0] data; 136 | 137 | assign data ={WRITE,SEQ,1'b0,cnt_address,PM,SHADOW,1'b0,RANGE,CODING,4'b0000}; //00001000011XXX001 138 | 139 | always@(posedge clk or negedge rst_n) 140 | begin 141 | if(!rst_n) 142 | begin 143 | adc_din <= 0; 144 | end 145 | 146 | else 147 | begin 148 | case(cnt0) 149 | 6'b000010:adc_din = data[15]; 150 | 6'b000100:adc_din = data[14]; 151 | 6'b000110:adc_din = data[13]; 152 | 6'b001000:adc_din = data[12]; 153 | 6'b001010:adc_din = data[11]; 154 | 6'b001100:adc_din = data[10]; 155 | 6'b001110:adc_din = data[9]; 156 | 6'b010000:adc_din = data[8]; 157 | 6'b010010:adc_din = data[7]; 158 | 6'b010100:adc_din = data[6]; 159 | 6'b010110:adc_din = data[5]; 160 | 6'b011000:adc_din = data[4]; 161 | 6'b011010:adc_din = data[3]; 162 | 6'b011100:adc_din = data[2]; 163 | 6'b011110:adc_din = data[1]; 164 | 6'b100000:adc_din = data[0]; 165 | //default: adc_din = 0; 166 | endcase 167 | end 168 | 169 | end 170 | 171 | //---------------------------------------------- 172 | 173 | //串转并 174 | reg [14:0] dout ; 175 | 176 | reg [4:0]cnt1; //计sclk的个数 0-16 177 | always@(posedge clk or negedge rst_n) 178 | begin 179 | if(!rst_n) 180 | cnt1<=0; 181 | 182 | else if(adc_sclk && adc_cs_n==0) 183 | if(cnt1==16) 184 | cnt1<=0; 185 | 186 | else 187 | cnt1<=cnt1+1; 188 | end 189 | 190 | 191 | always@(posedge clk or negedge rst_n ) 192 | begin 193 | if(!rst_n) 194 | dout <= 0; 195 | 196 | else if (cnt0==1 ) 197 | dout <= 0; 198 | 199 | else if ( cnt1<16 ) 200 | dout[15-cnt1] <= adc_dout; 201 | 202 | end 203 | //---------------------------------------------- 204 | 205 | 206 | //---------------------------------------------- 207 | //输出 208 | always@(posedge adc_cs_n or negedge rst_n) 209 | begin 210 | if(!rst_n) 211 | begin 212 | dout_0<=0; 213 | dout_1<=0; 214 | dout_2<=0; 215 | dout_3<=0; 216 | dout_4<=0; 217 | dout_5<=0; 218 | dout_6<=0; 219 | dout_7<=0; 220 | end 221 | else 222 | begin 223 | case (dout[14:12]) 224 | 3'b000: dout_0<=dout[11:0]; 225 | 3'b001: dout_1<=dout[11:0]; 226 | 3'b010: dout_2<=dout[11:0]; 227 | 3'b011: dout_3<=dout[11:0]; 228 | 3'b100: dout_4<=dout[11:0]; 229 | 3'b101: dout_5<=dout[11:0]; 230 | 3'b110: dout_6<=dout[11:0]; 231 | 3'b111: dout_7<=dout[11:0]; 232 | default: 233 | begin 234 | dout_0<=0; 235 | dout_1<=0; 236 | dout_2<=0; 237 | dout_3<=0; 238 | dout_4<=0; 239 | dout_5<=0; 240 | dout_6<=0; 241 | dout_7<=0; 242 | end 243 | endcase 244 | end 245 | end 246 | 247 | //---------------------------------------------- 248 | 249 | always@(posedge clk or negedge rst_n) 250 | begin 251 | if(!rst_n) 252 | begin 253 | dout_vld<=8'b0000_0000; 254 | end 255 | else if( cs_n_wrsigrise ==1) 256 | begin 257 | case (dout[14:12]) 258 | 3'b000: dout_vld<=8'b00000001; 259 | 3'b001: dout_vld<=8'b00000010; 260 | 3'b010: dout_vld<=8'b00000100; 261 | 3'b011: dout_vld<=8'b00001000; 262 | 3'b100: dout_vld<=8'b00010000; 263 | 3'b101: dout_vld<=8'b00100000; 264 | 3'b110: dout_vld<=8'b01000000; 265 | 3'b111: dout_vld<=8'b10000000; 266 | default:dout_vld<=8'b00000000; 267 | endcase 268 | end 269 | 270 | else 271 | dout_vld<=8'b00000000; 272 | end 273 | 274 | endmodule --------------------------------------------------------------------------------