效果
储备知识
- FFT IP核的调用。用来求出AD输入波形的峰峰值
- RAM、ROM IP核的调用,存储波形和文字信息
- VGA视频传输协议的时序设计
- DAC芯片的时序设计。DDS 信号发生器的设计,产生不同的测试波形
- PLL IP核的调用,产生不同频率的时钟
- Seg 6位数码管的动态驱动设计,显示频率信息
程序
程序比较乱,没有进行优化,有时间去整理一下
module seg(
input clk,
input rst_n,
input [19:0] tenvalue,
output reg [7:0] segdata,
output reg [2:0] segcs
);
reg [24:0] count1ms;
reg [2:0] number = 3'b0;
reg clk1ms = 1'b0;
parameter sample=2'b00,
display=2'b01;
//-----------数码管驱动时钟-----------
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk1ms <= 1'b0;
count1ms <= 0;
end else begin
if (count1ms >= 25'd50000) begin // 1ms的计数器
clk1ms <= ~clk1ms;
count1ms <= 0;
end else begin
count1ms <= count1ms + 1'b1;
end
end
end
//-----------数码管译码-----------
function [7:0] leddata;
input [3:0] datain;
begin
case (datain)
4'd0: leddata = 8'b11000000; // 0
4'd1: leddata = 8'b11111001; // 1
4'd2: leddata = 8'b10100100; // 2
4'd3: leddata = 8'b10110000; // 3
4'd4: leddata = 8'b10011001; // 4
4'd5: leddata = 8'b10010010; // 5
4'd6: leddata = 8'b10000010; // 6
4'd7: leddata = 8'b11111000; // 7
4'd8: leddata = 8'b10000000; // 8
4'd9: leddata = 8'b10010000; // 9
4'd10: leddata = 8'b10111111; // -
4'd11: leddata = 8'b01111111; // .
default: leddata = 8'b11111111;
endcase
end
endfunction
//-----------数码管扫描-----------
always @(posedge clk1ms or negedge rst_n) begin
if (!rst_n) begin
number <= 3'd0;
end else begin
if (number == 3'd5) begin
number <= 3'd0;
end else begin
number <= number + 1;
end
case (number)
3'd0: begin
segdata <= leddata(tenvalue % 10); // 个位
segcs <= 3'b101;
end
3'd1: begin
segdata <= leddata((tenvalue / 10) % 10); // 十位
segcs <= 3'b100;
end
3'd2: begin
segdata <= leddata((tenvalue / 100) % 10); // 百位
segcs <= 3'b011;
end
4'd3: begin
segdata <= leddata((tenvalue / 1000) % 10); // 千位
segcs <= 3'b010;
end
4'd4: begin
segdata <= leddata((tenvalue / 10000) % 10); // 万位
segcs <= 3'b001;
end
4'd5: begin
segdata <= leddata((tenvalue / 100000) % 10); // 十万位
segcs <= 3'b000;
end
default: begin
segdata <= 8'b11111111; // 或者其他默认值
segcs <= 3'b111; // 或者其他默认值
end
endcase
end
end
endmodule
`timescale 1ns/1ns
module freq_meter_calc
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire clk_test , //待检测时钟
output reg [19:0] freq //待检测时钟频率
);
parameter CNT_GATE_S_MAX = 28'd37_499_999 , //软件闸门计数器计数最大值 1.5s
CNT_RISE_MAX = 28'd6_250_000 ; //软件闸门拉高计数值, 1.25s
parameter CLK_STAND_FREQ = 28'd100_000_000 ; //标准时钟时钟频率, 100Mhz
wire clk_stand ;
wire gate_a_flag_s ;
wire gate_a_flag_t ;
reg [27:0] cnt_gate_s ;
reg gate_s ;
reg gate_a ;
reg gate_a_test ;
reg gate_a_stand ;
reg gate_a_stand_reg ;
reg gate_a_test_reg ;
reg [47:0] cnt_clk_stand ;
reg [47:0] cnt_clk_stand_reg ;
reg [47:0] cnt_clk_test ;
reg [47:0] cnt_clk_test_reg ;
reg calc_flag ;
reg [63:0] freq_reg ;
reg calc_flag_reg ;
//step1:按照原理生成软件闸门、实际闸门
//cnt_gate_s:软件闸门计数器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_gate_s <= 28'd0;
else if(cnt_gate_s == CNT_GATE_S_MAX)
cnt_gate_s <= 28'd0;
else
cnt_gate_s <= cnt_gate_s + 1'b1;
//gate_s:软件闸门
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_s <= 1'b0;
else if((cnt_gate_s>= CNT_RISE_MAX)
&& (cnt_gate_s <= (CNT_GATE_S_MAX - CNT_RISE_MAX)))
gate_s <= 1'b1;
else
gate_s <= 1'b0;
//gate_a:实际闸门
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a <= 1'b0;
else
gate_a <= gate_s;
//step2:得到待测信号的周期数 X
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_test <= 1'b0;
else
gate_a_test <= gate_a;
//gate_a_test:实际闸门打一拍(待检测时钟下)
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_test_reg <= 1'b0;
else
gate_a_test_reg <= gate_a_test;
//cnt_clk_test:待检测时钟周期计数器,计数实际闸门下待检测时钟周期数。 x++
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_test <= 48'd0;
else if(gate_a_test == 1'b0)
cnt_clk_test <= 48'd0;
else if(gate_a_test == 1'b1)
cnt_clk_test <= cnt_clk_test + 1'b1;
//gate_a_flag_t:实际闸门下降沿(待检测时钟下)
assign gate_a_flag_t = ((gate_a_test_reg == 1'b1) && (gate_a_test == 1'b0))
? 1'b1 : 1'b0;
//cnt_clk_test_reg:实际闸门下待检测时钟周期数, x
always@(posedge clk_test or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_test_reg <= 32'd0;
else if(gate_a_flag_t == 1'b1)
cnt_clk_test_reg <= cnt_clk_test;
//step3:得到标准信号的周期数 y
//使用PLL ipcore生成100Mhz信号
clk_gen clk_gen_inst
(
.areset (~sys_rst_n ),
.inclk0 (sys_clk ),
.c0 (clk_stand )
);
//gate_a_stand:实际闸门打一拍(标准时钟下)
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_stand <= 1'b0;
else
gate_a_stand <= gate_a_test;
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
gate_a_stand_reg <= 1'b0;
else
gate_a_stand_reg <= gate_a_stand;
//gate_a_flag_s:实际闸门下降沿(标准时钟下)
assign gate_a_flag_s = ((gate_a_stand_reg == 1'b1) && (gate_a_stand == 1'b0))
? 1'b1 : 1'b0;
//cnt_clk_stand:标准时钟周期计数器,计数实际闸门下标准时钟周期数。 y++
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_stand <= 48'd0;
else if(gate_a_stand == 1'b0)
cnt_clk_stand <= 48'd0;
else if(gate_a_stand == 1'b1)
cnt_clk_stand <= cnt_clk_stand + 1'b1;
//cnt_clk_stand_reg:实际闸门下标志时钟周期数
always@(posedge clk_stand or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk_stand_reg <= 32'd0;
else if(gate_a_flag_s == 1'b1)
cnt_clk_stand_reg <= cnt_clk_stand;
//step4: 利用公式进行频率计算
//calc_flag:待检测时钟时钟频率计算标志信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
calc_flag <= 1'b0;
else if(cnt_gate_s == (CNT_GATE_S_MAX - 1'b1))
calc_flag <= 1'b1;
else
calc_flag <= 1'b0;
//freq:待检测时钟信号时钟频率
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq_reg <= 64'd0;
else if(calc_flag == 1'b1)
freq_reg <= (CLK_STAND_FREQ * cnt_clk_test_reg / cnt_clk_stand_reg ); // (100MHZ*X)/Y
//calc_flag_reg:待检测时钟频率输出标志信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
calc_flag_reg <= 1'b0;
else
calc_flag_reg <= calc_flag;
//freq:待检测时钟信号时钟频率
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
freq <= 19'd0;
else if(calc_flag_reg == 1'b1)
freq <= (CLK_STAND_FREQ * cnt_clk_test_reg / (cnt_clk_stand_reg) );
endmodule
`timescale 1ns/1ns
/////////////////////////////////////////////////////////////////////////
// Author : EmbedFire
// Create Date : 2019/07/10
// Module Name : key_control
// Project Name : top_dds
// Target Devices: Altera EP4CE10F17C8N
// Tool Versions : Quartus 13.0
// Description : 按键控制模块,控制波形选择
//
// Revision : V1.0
// Additional Comments:
//
// 实验平台: 野火_征途Pro_FPGA开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
////////////////////////////////////////////////////////////////////////
module key_control
(
input wire sys_clk , //系统时钟,50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [3:0] key , //输入4位按键
output reg [3:0] wave_select //输出波形选择
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter sin_wave = 4'b0001, //正弦波
squ_wave = 4'b0010, //方波
tri_wave = 4'b0100, //三角波
saw_wave = 4'b1000; //锯齿波
parameter CNT_MAX = 20'd999_999; //计数器计数最大值
//wire define
wire key3 ; //按键3
wire key2 ; //按键2
wire key1 ; //按键1
wire key0 ; //按键0
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//wave:按键状态对应波形
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
wave_select <= 4'b0000;
else if(key0 == 1'b1)
wave_select <= sin_wave;
else if(key1 == 1'b1)
wave_select <= squ_wave;// 锯齿波
else if(key2 == 1'b1)
wave_select <= tri_wave;// 三角波
else if(key3 == 1'b1)
wave_select <= saw_wave;
else
wave_select <= wave_select;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- key_fifter_inst3 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst3
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[3] ) , //按键输入信号
.key_flag (key3 ) //按键消抖后标志信号
);
//------------- key_fifter_inst2 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst2
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[2] ) , //按键输入信号
.key_flag (key2 ) //按键消抖后标志信号
);
//------------- key_fifter_inst1 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst1
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[1] ) , //按键输入信号
.key_flag (key1 ) //按键消抖后标志信号
);
//------------- key_fifter_inst0 --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst0
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key[0] ) , //按键输入信号
.key_flag (key0 ) //按键消抖后标志信号
);
endmodule
module dds
(
input wire sys_clk , //系统时钟,50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [3:0] wave_select , //输出波形选择
output wire [7:0] data_out //波形输出
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter sin_wave = 4'b0001 , //正弦波
squ_wave = 4'b0010 , //方波
tri_wave = 4'b0100 , //三角波
saw_wave = 4'b1000 ; //锯齿波
parameter FREQ_CTRL = 32'd42949 , //相位累加器单次累加值
PHASE_CTRL = 12'd1024 ; //相位偏移量
//reg define
reg [31:0] fre_add ; //相位累加器
reg [11:0] rom_addr_reg; //相位调制后的相位码
reg [13:0] rom_addr ; //ROM读地址
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//fre_add:相位累加器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
fre_add <= 32'd0;
else
fre_add <= fre_add + FREQ_CTRL;
//rom_addr:ROM读地址
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
rom_addr <= 14'd0;
rom_addr_reg <= 11'd0;
end
else
case(wave_select)
sin_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
squ_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd4096;
end //方波
tri_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd8192;
end //三角波
saw_wave:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg + 14'd12288;
end //锯齿波
default:
begin
rom_addr_reg <= fre_add[31:20] + PHASE_CTRL;
rom_addr <= rom_addr_reg;
end //正弦波
endcase
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------------------- rom_wave_inst ------------------------
rom_wave rom_wave_inst
(
.address (rom_addr ), //ROM读地址
.clock (sys_clk ), //读时钟
.q (data_out ) //读出波形数据
);
endmodule
`timescale 1ns/1ns
////////////////////////////////////////////////////////////////////////
// Author : EmbedFire
// Create Date : 2019/03/15
// Module Name : key_filter
// Project Name : top_dds
// Target Devices: Altera EP4CE10F17C8N
// Tool Versions : Quartus 13.0
// Description : 按键消抖模块
//
// Revision : V1.0
// Additional Comments:
//
// 实验平台: 野火_征途Pro_FPGA开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
////////////////////////////////////////////////////////////////////////
module key_filter
#(
parameter CNT_MAX = 20'd999_999 //计数器计数最大值
)
(
input wire sys_clk , //系统时钟50Mhz
input wire sys_rst_n , //全局复位
input wire key_in , //按键输入信号
output reg key_flag //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//reg define
reg [19:0] cnt_20ms ; //计数器
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_20ms:如果时钟的上升沿检测到外部按键输入的值为低电平时,计数器开始计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'b0;
else if(key_in == 1'b1)
cnt_20ms <= 20'b0;
else if(cnt_20ms == CNT_MAX && key_in == 1'b0)
cnt_20ms <= cnt_20ms;
else
cnt_20ms <= cnt_20ms + 1'b1;
//key_flag:当计数满20ms后产生按键有效标志位
//且key_flag在999_999时拉高,维持一个时钟的高电平
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key_flag <= 1'b0;
else if(cnt_20ms == CNT_MAX - 1'b1)
key_flag <= 1'b1;
else
key_flag <= 1'b0;
endmodule
module serial_output
(
input wire sys_clk , // 系统时钟
input wire sys_rst_n , // 复位信号,低电平有效
input wire [7:0] dac_data , // 8位并行数据输入
output reg serial_out // 串行数据输出
);
// 寄存器和参数定义
reg [2:0] bit_count; // 位计数器,用于追踪当前正在输出的位
reg [7:0] data_reg; // 数据寄存器,用于暂存dac_data
// 时钟上升沿触发的逻辑
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
// 复位逻辑
bit_count <= 3'b0;
data_reg <= 8'b0;
serial_out <= 1'b0;
end else begin
// 串行输出逻辑
if (bit_count == 3'b111) begin
// 如果所有位都已输出,则重新加载数据并重置计数器
bit_count <= 3'b0;
data_reg <= dac_data;
end else begin
// 输出当前最高位,并将数据左移一位
serial_out <= data_reg[7];
data_reg <= data_reg << 1;
bit_count <= bit_count + 1;
end
end
end
endmodule
module tlc5620_driver
(
input CLOCK_50,
input RST_N,
//
input da_enable,
input da_range, // 0, 1倍参考电压; 1, 2倍参考电压
input [7:0] da0_data, // 0~255
input [7:0] da1_data, // 0~255
input [7:0] da2_data, // 0~255
input [7:0] da3_data, // 0~255
//
output reg SCK,
output reg SDI,
output reg LOAD
);
function integer log2(input integer n);
integer i;
for(i=0; 2**i <=n; i=i+1) log2=i+1;
endfunction
/**************************************
* 生成140ns的tick时钟
**************************************/
reg [log2(7):1]cnt_140ns;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) cnt_140ns <= 0;
else begin
if(cnt_140ns < 6)
cnt_140ns <= cnt_140ns + 1'b1;
else cnt_140ns <= 0;
end
wire tick_140ns = (cnt_140ns == 6) ? 1 : 0;
/**************************************
* 根据tick时钟生成da基准计数器
**************************************/
reg [log2(48):1] da_ref_cnt; // [0,47]
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) da_ref_cnt <= 0;
else begin
if(!da_enable) da_ref_cnt <= 0;
else begin
if(tick_140ns) begin
if(da_ref_cnt < 47)
da_ref_cnt <= da_ref_cnt + 1'b1;
else da_ref_cnt <= 0;
end
end
end
wire tick_6720ns = (da_ref_cnt == 47) ? 1 : 0;
reg [1:0] da_sel_cnt;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) da_sel_cnt <= 2'b0;
else if (tick_6720ns) begin
if(da_sel_cnt < 3)
da_sel_cnt <= da_sel_cnt + 1'b1;
else da_sel_cnt <= 2'b0;
end
/**************************************
* 根据基准计数器生成串行信号
**************************************/
reg [7:0] da_data;
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) da_data <= 8'b0;
else begin
case(da_sel_cnt)
2'b00: da_data <= da0_data;
2'b01: da_data <= da1_data;
2'b10: da_data <= da2_data;
2'b11: da_data <= da3_data;
endcase
end
always@(posedge CLOCK_50, negedge RST_N)
if(!RST_N) begin
SCK <= 0;
SDI <= 0;
LOAD <= 0;
end
else begin
if(tick_140ns) begin
// 生成SCK信号
case(da_ref_cnt)
2,6,10,14,18,22,26,30,34,38,42: SCK <= 1;
4,8,12,16,20,24,28,32,36,40,44: SCK <= 0;
default : ; // 缺省不操作
endcase
// 生成LOAD信号
case(da_ref_cnt)
0: LOAD <= 1;
46: LOAD <= 0;
default : ; // 缺省不操作
endcase
// 送入串型数据
case(da_ref_cnt)
3,4: SDI <= da_sel_cnt[1];
7,8: SDI <= da_sel_cnt[0];
11,12: SDI <= da_range;
15,16: SDI <= da_data[7];
19,20: SDI <= da_data[6];
23,24: SDI <= da_data[5];
27,28: SDI <= da_data[4];
31,32: SDI <= da_data[3];
35,36: SDI <= da_data[2];
39,40: SDI <= da_data[1];
43,44: SDI <= da_data[0];
default : SDI <= 1'b1;
endcase
end
end
endmodule
module top_dds
(
input wire sys_clk , // 系统时钟,50MHz
input wire sys_rst_n , // 复位信号,低电平有效
input wire [3:0] key , // 输入4位按键
input key_add , // 减少脉冲频率按键
input key_low , // 增加脉冲频率按键
// TLC5620的引脚
output wire da_clk , // 时钟信号
output wire da_data , // 数据信号
output wire da_ldac , // LDAC信号
output wire da_load // LOAD信号
);
// 定义计数器的最大值
reg [15:0] counter = 16'd999; // 初始值
// 消抖后的按键状态
wire key_add_flag;
wire key_low_flag;
// 消抖后的按键状态
parameter CNT_MAX = 20'd999_999; //计数器计数最大值
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
// 当复位信号为低时,重置计数器和步进信号
counter <= 16'd999;
end else begin
// 根据按键状态调整counter的值
if (!key_add_flag) begin
counter <= counter + 16'd100;
end else if (!key_low_flag) begin
counter <= counter - 16'd100;
end
end
end
/**************************************
* 生成20ms的tick时钟
**************************************/
reg [15:0] cnt_20ms;
always@(posedge sys_clk, negedge sys_rst_n)
if(!sys_rst_n) cnt_20ms <= 0;
else begin
if(cnt_20ms < 16'd999)
cnt_20ms <= cnt_20ms + 1'b1;
else cnt_20ms <= 0;
end
wire tick_20ms = (cnt_20ms == 16'd999) ? 1 : 0;
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire [3:0] wave_select ; // 波形选择
wire [7:0] dac_data ; // 输入DAC模块波形数据
/**************************************
* 锯齿波;
**************************************/
reg [7:0] da0_data;
always@(posedge sys_clk, negedge sys_rst_n)
if(!sys_rst_n) da0_data <= 0;
else if(tick_20ms) begin
if(da0_data < 126)
da0_data <= da0_data + 1'b1;
else da0_data <= 0;
end
/**************************************
* 三角波;
**************************************/
reg da1_highest_level_flag;
reg [7:0] da1_data;
always@(posedge sys_clk, negedge sys_rst_n)
if(!sys_rst_n) begin
da1_data <= 0;
da1_highest_level_flag <= 0;
end else if(tick_20ms) begin
if(da1_data == 126)
da1_highest_level_flag <= 1;
else if(da1_data == 0)
da1_highest_level_flag <= 0;
if(da1_highest_level_flag)
da1_data <= da1_data - 1'b1;
else
da1_data <= da1_data + 1'b1;
end
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//-------------------------- dds_inst -----------------------------
dds dds_inst
(
.sys_clk (sys_clk ), // 系统时钟,50MHz
.sys_rst_n (sys_rst_n ), // 复位信号,低电平有效
.wave_select (wave_select), // 输出波形选择
.data_out (dac_data ) // 波形输出
);
//----------------------- key_control_inst ------------------------
key_control key_control_inst
(
.sys_clk (sys_clk ), // 系统时钟,50MHz
.sys_rst_n (sys_rst_n ), // 复位信号,低电平有效
.key (key ), // 输入4位按键
.wave_select (wave_select) // 输出波形选择
);
//----------------------- tlc5620_driver_inst ------------------------
tlc5620_driver tlc5620_driver_inst
(
.CLOCK_50(sys_clk), // 系统时钟
.RST_N(sys_rst_n), // 复位信号
.da_enable(1'b1), // 使能信号,始终使能
.da_range(1'b0), // 输出范围选择,根据需要设置
.da0_data(dac_data), // 将dac_data连接到DA0通道
.da1_data(da0_data), // 其他通道暂时不使用,置为0
.da2_data(da1_data), // 其他通道暂时不使用,置为0
.da3_data(8'b0), // 其他通道暂时不使用,置为0
.SCK(da_clk), // 连接到外部引脚
.SDI(da_data), // 连接到外部引脚
.LOAD(da_load) // 连接到外部引脚
);
// TLC5620的LDAC信号通常需要保持低电平以更新输出电压
assign da_ldac = 1'b0;
//------------- key_low --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst5
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key_low ) , //按键输入信号
.key_flag (key_low_flag ) //按键消抖后标志信号
);
//------------- key_add --------------
key_filter
#(
.CNT_MAX (CNT_MAX ) //计数器计数最大值
)
key_filter_inst4
(
.sys_clk (sys_clk ) , //系统时钟50Mhz
.sys_rst_n (sys_rst_n) , //全局复位
.key_in (key_add ) , //按键输入信号
.key_flag (key_add_flag ) //按键消抖后标志信号
);
endmodule
//---------------------------------------------------------------------------
//-- 文件名 : A4_Vga.v
//-- 作者 : ZIRCON
//-- 描述 : VGA显示彩条
//-- 修订历史 : 2014-1-1
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//-- VGA 800*600@60
//-- VGA_DATA[7:0] red2,red1,red0,green2,green1,green0,blue1,blue0
//-- VGA CLOCK 40MHz.
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//-- Horizonal timing information
//-- Sync pluse 128 a
//-- back porch 88 b
//-- active 800 c
//-- front porch 40 d
//-- All line 1056 e
//-- Vertical timing information
//-- sync pluse 4 o
//-- back porch 23 p
//-- active time 600 q
//-- front porch 1 r
//-- All lines 628 s
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//-- Horizonal timing information
`define HSYNC_A 16'd128 // 128
`define HSYNC_B 16'd216 // 128 + 88
`define HSYNC_C 16'd1016 // 128 + 88 + 800
`define HSYNC_D 16'd1056 // 128 + 88 + 800 + 40
//-- Vertical timing information
`define VSYNC_O 16'd4 // 4
`define VSYNC_P 16'd27 // 4 + 23
`define VSYNC_Q 16'd627 // 4 + 23 + 600
`define VSYNC_R 16'd628 // 4 + 23 + 600 + 1
//---------------------------------------------------------------------------
module Vga_Module
(
//输入端口
CLK_40M,RST_N,vga_freq,vga_fengzhi,
//输出端口
VSYNC,HSYNC,VGA_DATA,vga_x,vga_y,ad_to_vga_data
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_40M; //时钟的端口
input RST_N; //复位的端口,低电平复位
input [7:0] ad_to_vga_data; //VGA中显示的波形数据
input [31:0] vga_freq; //VGA中显示的频率值
input [31:0] vga_fengzhi; //VGA中显示的峰峰值
output VSYNC; //VGA垂直同步端口
output HSYNC; //VGA水平同步端口
output [ 7:0] VGA_DATA; //VGA数据端口
output [15:0] vga_x; //VGA的x坐标
output [15:0] vga_y; //VGA的y坐标
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg [15:0] hsync_cnt; //水平扫描计数器
reg [15:0] hsync_cnt_n; //hsync_cnt的下一个状态
reg [15:0] vsync_cnt; //垂直扫描计数器
reg [15:0] vsync_cnt_n; //vsync_cnt的下一个状态
reg [ 7:0] VGA_DATA; //RGB端口总线
reg [ 7:0] VGA_DATA_N; //VGA_DATA的下一个状态
reg VSYNC; //垂直同步端口
reg VSYNC_N; //VSYNC的下一个状态
reg HSYNC; //水平同步端口
reg HSYNC_N; //HSYNC的下一个状态
reg vga_data_en; //RGB传输使能信号
reg vga_data_en_n; //vga_data_en的下一个状态
wire [15:0] rom_font_data; //字库的数据位
reg [15:0] rom_font_addr; //字库的地址位
reg [15:0] rom_font_addr_n; //rom_font_addr的下一个状态
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//时序电路,用来给hsync_cnt寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
hsync_cnt <= 16'b0; //初始化hsync_cnt值
else
hsync_cnt <= hsync_cnt_n; //用来给hsync_cnt赋值
end
//组合电路,水平扫描
always @ (*)
begin
if(hsync_cnt == `HSYNC_D) //判断水平扫描时序
hsync_cnt_n = 16'b0; //如果水平扫描完毕,计数器将会被清零
else
hsync_cnt_n = hsync_cnt + 1'b1; //如果水平没有扫描完毕,计数器继续累加
end
//时序电路,用来给vsync_cnt寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
vsync_cnt <= 16'b0; //给行扫描赋值
else
vsync_cnt <= vsync_cnt_n; //给行扫描赋值
end
//组合电路,垂直扫描
always @ (*)
begin
if((vsync_cnt == `VSYNC_R) && (hsync_cnt == `HSYNC_D))//判断垂直扫描时序
vsync_cnt_n = 16'b0; //如果垂直扫描完毕,计数器将会被清零
else if(hsync_cnt == `HSYNC_D) //判断水平扫描时序
vsync_cnt_n = vsync_cnt + 1'b1; //如果水平扫描完毕,计数器继续累加
else
vsync_cnt_n = vsync_cnt; //否则,计数器将保持不变
end
//时序电路,用来给HSYNC寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
HSYNC <= 1'b0; //初始化HSYNC值
else
HSYNC <= HSYNC_N; //用来给HSYNC赋值
end
//组合电路,将HSYNC_A区域置0,HSYNC_B+HSYNC_C+HSYNC_D置1
always @ (*)
begin
if(hsync_cnt < `HSYNC_A) //判断水平扫描时序
HSYNC_N = 1'b0; //如果在HSYNC_A区域,那么置0
else
HSYNC_N = 1'b1; //如果不在HSYNC_A区域,那么置1
end
//时序电路,用来给VSYNC寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
VSYNC <= 1'b0; //初始化VSYNC值
else
VSYNC <= VSYNC_N; //用来给VSYNC赋值
end
//组合电路,将VSYNC_A区域置0,VSYNC_P+VSYNC_Q+VSYNC_R置1
always @ (*)
begin
if(vsync_cnt < `VSYNC_O) //判断水平扫描时序
VSYNC_N = 1'b0; //如果在VSYNC_O区域,那么置0
else
VSYNC_N = 1'b1; //如果不在VSYNC_O区域,那么置1
end
//时序电路,用来给vga_data_en寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
vga_data_en <= 1'b0; //初始化vga_data_en值
else
vga_data_en <= vga_data_en_n; //用来给vga_data_en赋值
end
//组合电路,判断显示有效区(列像素>216&&列像素<1017&&行像素>27&&行像素<627)
always @ (*)
begin
if((hsync_cnt > `HSYNC_B && hsync_cnt <`HSYNC_C) &&
(vsync_cnt > `VSYNC_P && vsync_cnt < `VSYNC_Q))
vga_data_en_n = 1'b1; //如果在显示区域就给使能数据信号置1
else
vga_data_en_n = 1'b0; //如果不在显示区域就给使能数据信号置0
end
//时序电路,用来给VGA_DATA寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N) //判断复位
VGA_DATA <= 8'h0; //初始化VGA_DATA值
else
VGA_DATA <= VGA_DATA_N; //用来给VGA_DATA赋值
end
//例化ROM字库模块
ROM_Font_Module ROM_Font_Init
(
.address (rom_font_addr ), //字库的地址位
.clock (CLK_40M ), //字库的时钟
.q (rom_font_data ) //字库的数据位
);
//判断数字显示的位置
assign rom_5v_en = (vga_y >= 10'd90) && (vga_y <= 10'd106) && (vga_x >= 10'd98) && (vga_x <= 10'd116);
assign rom_4_375v_en = (vga_y >= 10'd122) && (vga_y <= 10'd138) && (vga_x >= 10'd66) && (vga_x <= 10'd116);
assign rom_3_75v_en = (vga_y >= 10'd154) && (vga_y <= 10'd170) && (vga_x >= 10'd74) && (vga_x <= 10'd116);
assign rom_3_125v_en = (vga_y >= 10'd186) && (vga_y <= 10'd203) && (vga_x >= 10'd66) && (vga_x <= 10'd116);
assign rom_2_5v_en = (vga_y >= 10'd218) && (vga_y <= 10'd234) && (vga_x >= 10'd82) && (vga_x <= 10'd116);
assign rom_1_875v_en = (vga_y >= 10'd250) && (vga_y <= 10'd266) && (vga_x >= 10'd66) && (vga_x <= 10'd116);
assign rom_1_25v_en = (vga_y >= 10'd282) && (vga_y <= 10'd298) && (vga_x >= 10'd74) && (vga_x <= 10'd116);
assign rom_0_625v_en = (vga_y >= 10'd314) && (vga_y <= 10'd330) && (vga_x >= 10'd66) && (vga_x <= 10'd116);
assign rom_0v_en = (vga_y >= 10'd346) && (vga_y <= 10'd362) && (vga_x >= 10'd98) && (vga_x <= 10'd116);
assign rom_pinlv_en = (vga_y > 10'd490) && (vga_y < 10'd507) && (vga_x >= 10'd130) && (vga_x <= 10'd176);
assign rom_500hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd220);
assign rom_333hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd220);
assign rom_833hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd220);
assign rom_166hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd220);
assign rom_666hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd220);
assign rom_1khz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd212);
assign rom_2000hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd214);
assign rom_1833hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd230);
assign rom_1666hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd230);
assign rom_1500hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd230);
assign rom_1333hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd230);
assign rom_1166hz_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd180) && (vga_x <= 10'd230);
assign rom_26v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_25v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_24v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_23v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_22v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_21v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_20v_en = (vga_y >= 10'd490) && (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd516);
assign rom_fengzhi_0v_en = (vga_y >= 10'd490) & (vga_y <= 10'd506) && (vga_x >= 10'd482) & (vga_x <= 10'd500);
assign rom_fengzhi_en = (vga_y >= 10'd490) & (vga_y <= 10'd506) & (vga_x >= 10'd416) & (vga_x <= 10'd482);
//时序电路,用来给rom_font_addr寄存器赋值
always @ (posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
rom_font_addr <= 8'd0;
else
rom_font_addr <= rom_font_addr_n;
end
//组合电路,用于生成字库的地址位
always @ (*)
begin
if(rom_5v_en)
begin
if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_4_375v_en)
begin
if(vga_x == 10'd66)
rom_font_addr_n = 8'h20;
else if(vga_x == 10'd74)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h38;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_3_75v_en)
begin
if(vga_x == 10'd74)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h38;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_3_125v_en)
begin
if(vga_x == 10'd66)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd74)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_2_5v_en)
begin
if(vga_x == 10'd82)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1_875v_en)
begin
if(vga_x == 10'd66)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd74)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h40;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h38;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1_25v_en)
begin
if(vga_x == 10'd74)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_0_625v_en)
begin
if(vga_x == 10'd66)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd74)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd82)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd90)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd98)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_0v_en)
begin
if(vga_x == 10'd98)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd106)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_166hz_en && (vga_freq == 10'd166))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_333hz_en && (vga_freq == 10'd333))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd188)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_500hz_en && (vga_freq == 10'd500))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd188)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_666hz_en && (vga_freq == 10'd666))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd188)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_833hz_en && (vga_freq == 10'd833))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h40;
else if(vga_x == 10'd188)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1khz_en && (vga_freq == 10'd1000))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 12'h0a0;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1166hz_en && (vga_freq == 32'd1166))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 10'h8;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd220)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1333hz_en && (vga_freq == 32'd1333))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 10'h18;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd220)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1500hz_en && (vga_freq == 32'd1500))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 10'h28;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd220)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1666hz_en && (vga_freq == 32'd1666))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 10'h30;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd220)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_1833hz_en && (vga_freq == 32'd1833))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd188)
rom_font_addr_n = 10'h40;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd212)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd220)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_2000hz_en && (vga_freq == 32'd2000))
begin
if(vga_x == 10'd180)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd188)
rom_font_addr_n = 12'h0a0;
else if(vga_x == 10'd196)
rom_font_addr_n = 8'h90;
else if(vga_x == 10'd204)
rom_font_addr_n = 8'h98;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_26v_en) && (vga_fengzhi == 10'd26))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h30;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_25v_en) && (vga_fengzhi == 10'd25))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h28;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_24v_en) && (vga_fengzhi == 10'd24))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h20;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_23v_en) && (vga_fengzhi == 10'd23))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h18;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_22v_en) && (vga_fengzhi == 10'd22))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_21v_en) && (vga_fengzhi == 10'd21))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h8;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_20v_en) && (vga_fengzhi == 10'd20))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h10;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h50;
else if(vga_x == 10'd498)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd506)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if((rom_fengzhi_0v_en) && (vga_fengzhi == 10'd0))
begin
if(vga_x == 10'd482)
rom_font_addr_n = 8'h0;
else if(vga_x == 10'd490)
rom_font_addr_n = 8'h58;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_pinlv_en)
begin
if(vga_x == 10'd130)
rom_font_addr_n = 8'h60;
else if(vga_x == 10'd146)
rom_font_addr_n = 8'h70;
else if(vga_x == 10'd162)
rom_font_addr_n = 8'h80;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else if(rom_fengzhi_en)
begin
if(vga_x == 10'd416)
rom_font_addr_n = 8'ha8;
else if(vga_x == 10'd432)
rom_font_addr_n = 8'hb8;
else if(vga_x == 10'd448)
rom_font_addr_n = 8'hc8;
else if(vga_x == 10'd464)
rom_font_addr_n = 8'hd8;
else
rom_font_addr_n = rom_font_addr + 1'b1;
end
else
rom_font_addr_n <= 15'b0;;
end
//组合电路,判断字符显示的位置并进行显示
always @ (*)
begin
if(vga_data_en)
begin
if( (vga_x >= 10'd128 && vga_x <= 10'd704) && (vga_y >= 10'd96 && vga_y <= 10'd480) )
begin
if(vga_y - 10'd97 == (ad_to_vga_data )) //显示波形
VGA_DATA_N = 10'd253;
else if((10'd0 == (vga_y % 10'd5)) && (10'd0 == (vga_x % 10'd32))) //画虚线
VGA_DATA_N = 10'd208;
else if((10'd0 == (vga_y % 10'd32)) && (10'd0 == (vga_x % 10'd5))) //画虚线
VGA_DATA_N = 10'd208;
else if((vga_y == 10'd96 || vga_y == 10'd480) && (vga_x >= 10'd96 && vga_x <= 10'd704)) //上下线
VGA_DATA_N = 10'd208;
else if((vga_x == 10'd128 || vga_x == 704) && (vga_y >= 96 && vga_y <= 480)) //左右线
VGA_DATA_N = 10'd208;
else if(vga_y == 10'd352 && vga_x >= 10'd96 && vga_x <= 10'd704) //X轴
VGA_DATA_N = 10'he0;
else if(vga_x == 416 && vga_y >= 10'd96 && vga_y <= 10'd480) //Y轴
VGA_DATA_N = 10'he0;
else
VGA_DATA_N = 8'h08;
end
else if(rom_5v_en) //在屏幕上显示5V
begin
if(rom_font_data[10'd106 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_4_375v_en) //在屏幕上显示4.375V
begin
if(rom_font_data[10'd138 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_3_75v_en) //在屏幕上显示3.75V
begin
if(rom_font_data[10'd170 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_3_125v_en) //在屏幕上显示3.125V
begin
if(rom_font_data[10'd202 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_2_5v_en) //在屏幕上显示2.5V
begin
if(rom_font_data[10'd234 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_1_875v_en) //在屏幕上显示1.875V
begin
if(rom_font_data[10'd266 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_1_25v_en) //在屏幕上显示1.25V
begin
if(rom_font_data[10'd298 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_0_625v_en) //在屏幕上显示0.625V
begin
if(rom_font_data[10'd330 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_0v_en) //在屏幕上显示0V
begin
if(rom_font_data[10'd362 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if(rom_pinlv_en) //在屏幕上显示频率两个字
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_500hz_en) && (vga_freq == 10'd500)) //在屏幕上显示500hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_333hz_en) && (vga_freq == 10'd333)) //在屏幕上显示333hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_166hz_en) && (vga_freq == 10'd166)) //在屏幕上显示166hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_666hz_en) && (vga_freq == 10'd666)) //在屏幕上显示666hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_833hz_en) && (vga_freq == 10'd833)) //在屏幕上显示833hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1khz_en) && (vga_freq == 32'd1000)) //在屏幕上显示1khz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1166hz_en) && (vga_freq == 32'd1166)) //在屏幕上显示1166hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1333hz_en) && (vga_freq == 32'd1333)) //在屏幕上显示1333hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1500hz_en) && (vga_freq == 32'd1500)) //在屏幕上显示1500hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1666hz_en) && (vga_freq == 32'd1666)) //在屏幕上显示1666hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_1833hz_en) && (vga_freq == 32'd1833)) //在屏幕上显示1833hz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_2000hz_en) && (vga_freq == 32'd2000)) //在屏幕上显示2khz
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_fengzhi_en)) //在屏幕上显示峰峰值3个字
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_26v_en) && (vga_fengzhi == 10'd26)) //在屏幕上显示2.6V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_25v_en) && (vga_fengzhi == 10'd25)) //在屏幕上显示2.5V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_24v_en) && (vga_fengzhi == 10'd24)) //在屏幕上显示2.4V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_23v_en) && (vga_fengzhi == 10'd23)) //在屏幕上显示2.3V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_22v_en) && (vga_fengzhi == 10'd22)) //在屏幕上显示2.2V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_21v_en) && (vga_fengzhi == 10'd21)) //在屏幕上显示2.1V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_20v_en) && (vga_fengzhi == 10'd20)) //在屏幕上显示2.0V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else if((rom_fengzhi_0v_en) && (vga_fengzhi == 10'd0)) //在屏幕上显示0V
begin
if(rom_font_data[10'd506 - vga_y])
VGA_DATA_N = 10'd253;
else
VGA_DATA_N = 8'h03;
end
else
VGA_DATA_N = 8'h03;
end
else
VGA_DATA_N = 8'h0;
end
assign vga_x = hsync_cnt - `HSYNC_B;
assign vga_y = vsync_cnt - `VSYNC_P;
endmodule
//---------------------------------------------------------------------------
//-- 文件名 : FFT_Control_Module.v
//-- 作者 : ZIRCON
//-- 描述 : FFT控制模块
//-- 修订历史 : 2017-01-01
//---------------------------------------------------------------------------
module FFT_Control_Module
(
//输入端口
CLK_50M,RST_N,data_real_in_int,
//输出端口
fft_real_out_int,fft_imag_out_int,fft_bit_cnt,
,vga_fengzhi
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟端口
input RST_N; //复位端口
input [ 9:0] data_real_in_int; //输入波形数据
output [31:0] vga_fengzhi; //VGA中显示的峰峰值
output [ 9:0] fft_bit_cnt; //FFT位计数器
output [ 9:0] fft_real_out_int; //FFT实数的输出
output [ 9:0] fft_imag_out_int; //FFT虚数的输出
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
wire sink_sop; //输入流的开始信号
wire sink_eop; //输入流的结束信号
wire inverse; //FFT控制信号,1:IFFT,0:FFT
wire [ 1:0] sink_error; //输入错误信号
wire source_ready; //输出源准备信号
wire sink_ready; //输入的准备信号
wire [ 1:0] source_error; //输出源的错误信号
wire source_sop; //输出源流的开始信号
wire source_eop; //输出源流的结束信号
reg end_test; //结束测试信号
reg end_test_n; //end_test的下一个状态
wire source_valid; //输出源的有效信号
wire [ 5:0] source_exp; //输出源的指数信号
wire [ 9:0] source_real; //输出源的实部信号
wire [ 9:0] source_imag; //输出源的虚部信号
reg fft_start; //FFT开始转换信号
reg fft_start_n; //fft_start的下一个状态
wire end_input; //停止输入信号
wire end_output; //停止输出信号
reg [ 9:0] fft_bit_cnt; //FFT位计数器
reg [ 9:0] fft_bit_cnt_n; //fft_bit_cnt的下一个状态
reg [ 9:0] sink_real; //输入的实部信号
reg [ 9:0] sink_real_n; //sink_real的下一个状态
reg [ 9:0] sink_imag; //输入的虚部信号
reg [ 9:0] sink_imag_n; //sink_imag的下一个状态
reg sink_valid; //输入的有效信号
reg sink_valid_n; //sink_valid的下一个状态
reg [ 9:0] fft_real_out_int; //FFT输出的实部信号
reg [ 9:0] fft_real_out_int_n; //fft_real_out_int的下一个状态
reg [ 9:0] fft_imag_out_int; //FFT输出的虚部信号
reg [ 9:0] fft_imag_out_int_n; //fft_imag_out_int的下一个状态
reg [ 5:0] exponent_out_int; //FFT输出的指数信号
reg [ 5:0] exponent_out_int_n; //exponent_out_int的下一个状态
reg [31:0] fft_real_image_data; //FFT输出的数据信号
reg [31:0] fft_real_image_data_n;//fft_real_image_data的下一个状态
wire [15:0] sqrt_data_out; //平方根处理后的数据信号
reg [ 9:0] data_max; //数据的最大值
reg [ 9:0] data_max_n; //data_max的下一个状态
reg [ 9:0] data_max2; //数据的次大值
reg [ 9:0] data_max2_n; //data_max2的下一个状态
reg [ 9:0] max_cnt; //最大值的位置
reg [ 9:0] max_cnt_n; //max_cnt的下一个状态
reg [ 9:0] max_cnt2; //次大值的位置
reg [ 9:0] max_cnt2_n; //max_cnt2的下一个状态
reg [15:0] fengzhi_max; //峰峰值的最大值
reg [15:0] fengzhi_max_n; //fengzhi_max的下一个状态
reg [15:0] fengzhi_min; //峰峰值的最小值
reg [15:0] fengzhi_min_n; //fengzhi_min的下一个状态
parameter data_imag_in_int = 10'b0; //输入数据的虚部置0
parameter fftpts_array = 255; //FFT的点数
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
/* FFT控制信号,1:IFFT,0:FFT */
assign inverse = 1'b0;
/* 输入错误信号 */
assign sink_error = 2'b0;
/* 源准备信号 */
assign source_ready = 1'b1;
/* 输入开始进行FFT转换运算 */
assign fft_ready_valid = (sink_valid && sink_ready);
/* 时序电路,用来给fft_start寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fft_start <= 1'b1;
else
fft_start <= fft_start_n;
end
/* 组合电路,FFT开始转换信号 */
always @ (*)
begin
if(fft_ready_valid)
fft_start_n = 1'b0;
else
fft_start_n = 1'b1;
end
/* 时序电路,用来给fft_bit_cnt寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fft_bit_cnt <= 10'b0;
else
fft_bit_cnt <= fft_bit_cnt_n;
end
/* 组合电路,FFT位计数器 */
always @ (*)
begin
if(fft_ready_valid && (fft_bit_cnt == fftpts_array))
fft_bit_cnt_n = 1'b0;
else if(fft_ready_valid)
fft_bit_cnt_n = fft_bit_cnt + 1'b1;
else
fft_bit_cnt_n = fft_bit_cnt;
end
/* 停止输出信号 */
assign end_output = (source_eop && source_valid && source_ready) ? 1'b1 : 1'b0;
/* 停止输入信号 */
assign end_input = (sink_eop && sink_valid && sink_ready) ? 1'b1 : 1'b0;
/* 输入流的开始 */
assign sink_sop = (fft_bit_cnt == 1'b0) ? 1'b1 : 1'b0 ;
/* 输入流的结束 */
assign sink_eop = (fft_bit_cnt == fftpts_array) ? 1'b1 : 1'b0;
/* 时序电路,用来给end_test寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
end_test <= 1'b0;
else
end_test <= end_test_n;
end
/* 组合电路,结束测试信号 */
always @ (*)
begin
if(end_input)
end_test_n = 1'b1;
else
end_test_n = end_test;
end
/* 时序电路,用来给sink_real寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
sink_real <= 10'b0;
else
sink_real <= sink_real_n;
end
/* 组合电路,输入的实部信号 */
always @ (*)
begin
if(end_test || end_input)
sink_real_n = 10'b0;
else if (fft_ready_valid || (fft_start & !(sink_valid && sink_ready == 1'b0)))
sink_real_n = data_real_in_int;
else
sink_real_n = sink_real;
end
/* 时序电路,用来给sink_imag寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
sink_imag <= 10'b0;
else
sink_imag <= sink_imag_n;
end
/* 组合电路,输入的虚部信号 */
always @ (*)
begin
if(end_test || end_input)
sink_imag_n = 10'b0;
else if (fft_ready_valid || (fft_start & !(sink_valid && sink_ready == 1'b0)))
sink_imag_n = data_imag_in_int;
else
sink_imag_n = sink_imag;
end
/* 时序电路,用来给sink_valid寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
sink_valid <= 1'b0;
else
sink_valid <= sink_valid_n;
end
/* 组合电路,输入的有效信号 */
always @ (*)
begin
if(end_test || end_input)
sink_valid_n = 1'b0;
else if (fft_ready_valid || (fft_start & !(sink_valid && sink_ready == 1'b0)))
sink_valid_n = 1'b1;
else
sink_valid_n = 1'b1;
end
/* 时序电路,用来给fft_real_out_int寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fft_real_out_int <= 10'b0;
else
fft_real_out_int <= fft_real_out_int_n;
end
/* 组合电路,FFT输出的实部信号 */
always @ (*)
begin
if(source_valid && source_ready)
fft_real_out_int_n = source_real[9] ? (~source_real[9:0]+1) : source_real;
else
fft_real_out_int_n = fft_real_out_int;
end
/* 时序电路,用来给fft_imag_out_int寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fft_imag_out_int <= 10'b0;
else
fft_imag_out_int <= fft_imag_out_int_n;
end
/* 组合电路,FFT输出的虚部信号 */
always @ (*)
begin
if(source_valid && source_ready)
fft_imag_out_int_n = source_imag[9] ? (~source_imag[9:0]+1) : source_imag;
else
fft_imag_out_int_n = fft_imag_out_int;
end
/* 时序电路,用来给exponent_out_int寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
exponent_out_int <= 10'b0;
else
exponent_out_int <= exponent_out_int_n;
end
/* 组合电路,用于生成FFT输出的指数信号 */
always @ (*)
begin
if(source_valid && source_ready)
exponent_out_int_n = source_exp;
else
exponent_out_int_n = exponent_out_int;
end
/* 时序电路,用来给fft_real_image_data寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fft_real_image_data <= 32'b0;
else
fft_real_image_data <= fft_real_image_data_n;
end
/* 组合电路,用于生成FFT输出的数据信号 */
always @ (*)
begin
if(source_valid && source_ready)
fft_real_image_data_n = fft_real_out_int*fft_real_out_int + fft_imag_out_int*fft_imag_out_int;
else
fft_real_image_data_n = fft_real_image_data;
end
/* 平方根模块 */
SQRT_Module SQRT_Init
(
.radical (fft_real_image_data ), //FFT输出的数据信号
.q (sqrt_data_out ) //平方根处理后的数据信号
);
/* 时序电路,用来给max_cnt2寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
max_cnt2 <= 10'b0;
else
max_cnt2 <= max_cnt2_n;
end
/* 组合电路,用于生成次大值的位置 */
always @ (*)
begin
if(sqrt_data_out > data_max)
max_cnt2_n = max_cnt2 + 1'b1;
else if((sqrt_data_out > data_max2) && (sqrt_data_out != data_max))
max_cnt2_n = max_cnt2 + 1'b1;
else if(max_cnt2 >= 10'd256)
max_cnt2_n = 10'b0;
else
max_cnt2_n = max_cnt2 + 1'b1;;
end
/* 时序电路,用来给fengzhi_max寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fengzhi_max <= 16'b0;
else
fengzhi_max <= fengzhi_max_n;
end
/* 组合电路,用于生成峰峰值的最大值 */
always @ (*)
begin
if(data_real_in_int > fengzhi_max)
fengzhi_max_n = data_real_in_int;
else
fengzhi_max_n = fengzhi_max;
end
/* 时序电路,用来给fengzhi_max寄存器赋值 */
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
fengzhi_min <= 16'd255;
else
fengzhi_min <= fengzhi_min_n;
end
/* 组合电路,用于求出峰峰值的最小值 */
always @ (*)
begin
if(fengzhi_min > data_real_in_int)
fengzhi_min_n = data_real_in_int;
else
fengzhi_min_n = fengzhi_min;
end
/* 组合电路,生成VGA中显示的频率值 */
/* 组合电路,生成VGA中显示的峰峰值 */
assign vga_fengzhi = ((fengzhi_max - fengzhi_min) * 10'd50) >> 8'd8; //((data_max3 * 10'd100) >> 8'd8) + 10'd2;
/* FFT IP核模块例化 */
fft fft_init
(
.clk (CLK_50M ), //时钟端口
.reset_n (RST_N ), //复位端口
.inverse (inverse ), //FFT控制信号,1:IFFT,0:FFT
.sink_valid (sink_valid ), //输入的有效信号
.sink_sop (sink_sop ), //输入流的开始信号
.sink_eop (sink_eop ), //输入流的结束信号
.sink_real (sink_real ), //输入的实部信号
.sink_imag (sink_imag ), //输入的虚部信号
.sink_error (sink_error ), //输入错误信号
.source_ready (source_ready ), //输出源准备信号
.sink_ready (sink_ready ), //输入的准备信号
.source_error (source_error ), //输出源的错误信号
.source_sop (source_sop ), //输出源流的开始信号
.source_eop (source_eop ), //输出源流的结束信号
.source_valid (source_valid ), //输出源的有效信号
.source_exp (source_exp ), //输出源的指数信号
.source_real (source_real ), //输出源的实部信号
.source_imag (source_imag ) //输出源的虚部信号
);
endmodule
//---------------------------------------------------------------------------
//-- 文件名 : Ad_Module.v
//-- 作者 : ZIRCON
//-- 描述 : AD模块
//-- 修订历史 : 2014-1-1
//---------------------------------------------------------------------------
`define AD_CLK_TIME 10'd45 //1.1M, 909ns,909 / (1 / 50M) = 45 =0x2D
`define AD_CLK_TIME_HALF 10'd22 //909ns / 2 = 454.5ns 45 / 2 = 22
module Ad_Module
(
//Input
CLK_50M,RST_N,
//Output
AD_CS,AD_CLK,AD_DATA,data_out
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟的端口,开发板用的50M晶振
input RST_N; //复位的端口,低电平复位
input AD_DATA; //AD数据端口
output AD_CS; //AD片选端口
output AD_CLK; //AD时钟端口,最大不超过1.1MHz
output [ 7:0] data_out; //AD模数转换完成的数据输出
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg AD_CS; //AD片选信号端口
reg AD_CS_N; //AD_CS的下一个状态
reg AD_CLK; //AD时钟,最大不超过1.1MHz
reg AD_CLK_N; //AD_CLK的下一个状态
reg [ 2:0] ad_fsm_cs; //状态机的当前状态
reg [ 2:0] ad_fsm_ns; //状态机的下一个状态
reg [ 5:0] time_cnt; //用于记录一个时钟所用时间的定时器
reg [ 5:0] time_cnt_n; //time_cnt的下一个状态
reg [ 5:0] bit_cnt; //用来记录时钟周期个数的计数器
reg [ 5:0] bit_cnt_n; //bit_cnt的下一个状态
reg [ 7:0] data_out; //用来保存稳定的AD数据
reg [ 7:0] data_out_n; //data_out的下一个状态
reg [ 7:0] ad_data_reg; //用于保存数据的移位寄存器
reg [ 7:0] ad_data_reg_n; //ad_data_reg_n的下一个状态
parameter FSM_IDLE = 3'h0; //状态机的初始状态;
parameter FSM_READY = 3'h1; //满足CS有效时的第一个1.4us的延时状态
parameter FSM_DATA = 3'h2; //读取8个数据状态
parameter FSM_WAIT_CONV = 3'h3; //等待转换状态,等待17us;
parameter FSM_END = 3'h4; //结束的状态
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//时序电路,用来给ad_fsm_cs寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
ad_fsm_cs <= 1'b0; //初始化ad_fsm_cs值
else
ad_fsm_cs <= ad_fsm_ns; //用来给ad_fsm_ns赋值
end
//组合电路,用来实现状态机
always @ (*)
begin
case(ad_fsm_cs) //判断状态机的当前状态
FSM_IDLE:
//3 x 0.909us = 2.727us用于初始化延时
if((bit_cnt == 6'd2 ) && (time_cnt == `AD_CLK_TIME))
ad_fsm_ns = FSM_READY; //如果空闲状态完成就进入延时状态
else
ad_fsm_ns = ad_fsm_cs; //否则保持原状态不变
FSM_READY:
//2 x 0.909us = 1.818us用于延迟1.4us
if((bit_cnt == 6'd1 ) && (time_cnt == `AD_CLK_TIME))
ad_fsm_ns = FSM_DATA; //如果延时状态完成就进入读取数据状态
else
ad_fsm_ns = ad_fsm_cs; //否则保持原状态不变
FSM_DATA:
//读取数据8位,1~8个时钟脉冲
if((bit_cnt == 6'd8 ) && (time_cnt == `AD_CLK_TIME))
ad_fsm_ns = FSM_WAIT_CONV;//如果读取数据状态完成就进入等待状态
else
ad_fsm_ns = ad_fsm_cs; //否则保持原状态不变
FSM_WAIT_CONV:
//19 x 0.909us = 17.271us用于延迟17us
if((bit_cnt == 6'd18) && (time_cnt == `AD_CLK_TIME))
ad_fsm_ns = FSM_END; //如果等待状态完成就进入读取状态
else
ad_fsm_ns = ad_fsm_cs; //否则保持原状态不变
FSM_END:
ad_fsm_ns = FSM_READY; //完成一次数据转换,进入下一次转换
default:ad_fsm_ns = FSM_IDLE;
endcase
end
//时序电路,用来给time_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
time_cnt <= 6'h0; //初始化time_cnt值
else
time_cnt <= time_cnt_n; //用来给time_cnt赋值
end
//组合电路,实现0.909us的定时计数器
always @ (*)
begin
if(time_cnt == `AD_CLK_TIME) //判断0.909us时间
time_cnt_n = 6'h0; //如果到达0.909us,定时器清零
else
time_cnt_n = time_cnt + 6'h1; //如果未到0.909us,定时器继续加1
end
//时序电路,用来给bit_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
bit_cnt <= 6'h0; //初始化bit_cnt值
else
bit_cnt <= bit_cnt_n; //用来给bit_cnt赋值
end
//组合电路,用来记录时钟周期个数的计数器
always @ (*)
begin
if(ad_fsm_cs != ad_fsm_ns) //判断状态机的当前状态
bit_cnt_n = 6'h0; //如果当前的状态不等于下一个状态,计时器就清零
else if(time_cnt == `AD_CLK_TIME_HALF)//判断0.4545us时间
bit_cnt_n = bit_cnt + 6'h1; //如果到达0.4545us,计数器就加1
else
bit_cnt_n = bit_cnt; //否则计数器保持不变
end
//时序电路,用来给AD_CLK寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
AD_CLK <= 1'h0; //初始化AD_CLK值
else
AD_CLK <= AD_CLK_N; //用来给AD_CLK赋值
end
//组合电路,用来生成AD的时钟波形
always @ (*)
begin
if(ad_fsm_cs != FSM_DATA) //判断状态机的当前状态
AD_CLK_N = 1'h0; //如果当前的状态不等于读取数据状态,AD_CLK_N就置0
else if(time_cnt == `AD_CLK_TIME_HALF)//判断0.4545us时间
AD_CLK_N = 1'h1; //如果到达0.4545us,ADC_CLK_N就置1
else if(time_cnt == `AD_CLK_TIME)//判断0.909us时间
AD_CLK_N = 1'h0; //如果到达0.909us,AD_CLK_N就置0
else
AD_CLK_N = AD_CLK; //否则保持不变
end
//时序电路,用来给AD_CS寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
AD_CS <= 1'h0; //初始化AD_CS值
else
AD_CS <= AD_CS_N; //用来给AD_CS赋值
end
//组合电路,用来生成AD的片选波形
always @ (*)
begin
if((ad_fsm_cs == FSM_DATA) || (ad_fsm_cs == FSM_READY))//判断状态机的当前状态
AD_CS_N = 1'h0;//如果当前的状态等于读取数据状态或等于延时1.4us状态,AD_CS_N就置0
else
AD_CS_N = 1'h1;//如果当前的状态不等于读取数据状态或不等于延时1.4us状态,AD_CS_N就置1
end
//时序电路,用来给ad_data_reg寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
ad_data_reg <= 8'h0; //初始化ad_data_reg值
else
ad_data_reg <= ad_data_reg_n; //用来给ad_data_reg赋值
end
//组合电路,将AD线上的数据保存到移位寄存器中
always @(*)
begin
if((ad_fsm_cs == FSM_DATA) && (!AD_CLK) && (AD_CLK_N))//判断每一个时钟的上升沿
ad_data_reg_n = {ad_data_reg[6:0],AD_DATA};//将数据存入移位寄存器中,高位优先
else
ad_data_reg_n = ad_data_reg; //否则保持不变
end
//时序电路,用来给data_out寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
data_out <= 8'h0; //初始化data_out值
else
data_out <= data_out_n; //用来给data_out赋值
end
//组合电路,将移位寄存器中的数据存入data_out中,可用于输出
always @ (*)
begin
if(ad_fsm_cs == FSM_END) //判断复位
data_out_n = ad_data_reg; //初始化data_out值
else
data_out_n = data_out; //用来给data_out赋值
end
endmodule
module A4_Oscilloscope_Top
(
//时钟和复位端口
input CLK_50M,
input RST_N,
//AD外设端口
output AD_CS,
output AD_CLK,
input AD_DATA,
//DA外设端口
output da_clk ,
output da_data ,
output da_ldac ,
output da_load ,
input [3:0] key ,
//VGA外设端口
output VGA_HSYNC,
output VGA_VSYNC,
output [ 7:0] VGA_DATA,
input key_add , // 减少脉冲频率按键
input key_low , // 增加脉冲频率按键
//seg
input wire clk_test,
output wire clk_out , //生成的待检测时钟
output wire [7:0]segdata,
output wire [2:0]segcs
);
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
wire clk_40m; //PLL生成的40M时钟
wire [ 7:0] in_ad_data; //AD模数转换完成的数据输出
wire [15:0] vga_x; //VGA的x坐标
wire [31:0] vga_fengzhi; //VGA中显示的峰峰值
wire [ 7:0] ad_to_vga_data; //VGA中显示的波形数据
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
// 实例化DA模块
top_dds top_dds_inst
(
.sys_clk (CLK_50M) , // 系统时钟,50MHz
.sys_rst_n (RST_N) , // 复位信号,低电平有效
.key (key) , // 输入4位按键
.key_add (key_add) , // 输入按键
.key_low (key_low) , // 输入按键
.da_clk (da_clk) , // 时钟信号
.da_data (da_data) , // 数据信号
.da_ldac (da_ldac) , // LDAC信号
.da_load (da_load) , // LOAD信号
);
//例化AD模块
Ad_Module Ad_Init
(
.CLK_50M (CLK_50M ), //时钟端口
.RST_N (RST_N ), //复位端口
.AD_CS (AD_CS ), //AD片选端口
.AD_CLK (AD_CLK ), //AD时钟,最大不超过1.1MHz
.AD_DATA (AD_DATA ), //AD数据端口
.data_out (in_ad_data ) //AD模数转换完成的数据输出
);
Data_Process Data_Process_Init
(
.CLK_50M (CLK_50M ), //系统时钟50MHz
.CLK_40M (clk_40m ), //PLL生成的40MHz时钟
.RST_N (RST_N ), //复位端口
.AD_CS (AD_CS ), //AD片选端口
.in_ad_data (in_ad_data ), //AD模数转换完成的数据输出
.vga_x (vga_x ), //VGA的x坐标
.vga_fengzhi (vga_fengzhi ), //VGA中显示的峰峰值
.ad_to_vga_data(ad_to_vga_data) //VGA中显示的波形数据
);
//例化PLL模块
PLL_Module PLL_Module_Init
(
.inclk0 (CLK_50M ), //系统时钟50MHz
.c0 (clk_40m ) //PLL生成的40MHz时钟
);
//例化VGA模块
Vga_Module VGA_Init
(
.RST_N (RST_N ), //复位端口
.CLK_40M (clk_40m ), //PLL生成的40MHz时钟
.VSYNC (VGA_VSYNC ), //VGA垂直同步端口
.HSYNC (VGA_HSYNC ), //VGA水平同步端口
.VGA_DATA (VGA_DATA ), //VGA数据端口
.vga_x (vga_x ), //VGA的x坐标
.ad_to_vga_data(ad_to_vga_data), //VGA中显示的波形数据
.vga_freq (20'd500 ), //VGA中显示的频率值
.vga_fengzhi (vga_fengzhi ) //VGA中显示的峰峰值
);
//wire define
wire [19:0] freq ; //计算得到的待检测信号时钟频率
//------------- freq_meter_calc_inst --------------
freq_meter_calc freq_meter_calc_inst
(
.sys_clk (clk_40m ), //系统时钟,频率50MHz
.sys_rst_n (RST_N ), //复位信号,低电平有效
.clk_test (da_data ), //待检测时钟
.freq (freq ) //待检测时钟频率
);
seg seg_inst (
.clk(clk_40m),
.rst_n(RST_N),
.tenvalue(20'd500), // 这里连接没有问题
.segdata(segdata),
.segcs(segcs)
);
endmodule
module Data_Process
(
//输入端口
CLK_50M,CLK_40M,RST_N,AD_CS,in_ad_data,vga_x
//输出端口
,vga_fengzhi,ad_to_vga_data
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input CLK_50M; //时钟端口,开发板用的50M晶振
input CLK_40M; //PLL生成的40M时钟
input RST_N; //复位端口,低电平复位
input AD_CS; //AD片选信号端口
input [ 7:0] in_ad_data; //AD模数转换完成的数据输出
input [15:0] vga_x; //VGA的x坐标
output [31:0] vga_fengzhi; //VGA中显示的峰峰值
output [ 7:0] ad_to_vga_data; //VGA中显示的波形数据
//---------------------------------------------------------------------------
//-- 内部端口声明
//---------------------------------------------------------------------------
reg [ 1:0] detect_edge; //记录AD_CS的开始脉冲,即第一个上降沿
wire [ 1:0] detect_edge_n; //detect_edge的下一个状态
reg posedge_reg; //上升沿标志
wire posedge_reg_n; //posedge_reg的下一个状态
reg [15:0] ad_to_vga_addr; //读取AD到VGA的地址
reg [15:0] ad_to_vga_addr_n; //ad_to_vga_addr的下一个状态
reg [15:0] ad_to_fft_addr; //读取AD到FFT的地址
reg [15:0] ad_to_fft_addr_n; //ad_to_fft_addr的下一个状态
reg [26:0] time_cnt; //定时计数器
reg [26:0] time_cnt_n; //time_cnt的下一个状态
reg fft_rst_flag; //FFT模块复位标志位
reg fft_rst_flag_n; //fft_rst_flag标志位
wire [ 9:0] fft_bit_cnt; //FFT位计数器
wire [ 9:0] fft_real_out_int; //FFT实数的输出
wire [ 9:0] fft_imag_out_int; //FFT虚数的输出
wire [ 9:0] ad_to_fft_data; //FFT中用到的AD数据
wire [31:0] vga_freq; //VGA中显示的频率值
wire [31:0] vga_fengzhi; //VGA中显示的峰峰值
//设置定时器的时间为1s,计算方法为 (1*10^6)ns / (1/50)ns 50MHz为开发板晶振
parameter SET_TIME_1S = 27'd50_000_000;
//---------------------------------------------------------------------------
//-- 逻辑功能实现
//---------------------------------------------------------------------------
//时序电路,用来给detect_edge寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
detect_edge <= 2'b11; //初始化detect_edge值
else
detect_edge <= detect_edge_n; //用来给detect_edge赋值
end
//组合电路,检测上升沿
assign detect_edge_n = {detect_edge[0] , AD_CS}; //接收AD_CS的时钟信号
//时序电路,用来给posedge_reg寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
posedge_reg <= 1'b0; //初始化posedge_reg值
else
posedge_reg <= posedge_reg_n; //用来给posedge_reg赋值
end
//组合电路,判断上升沿,如果detect_edge等于01,posedge_reg_n就置1
assign posedge_reg_n = (detect_edge == 2'b01) ? 1'b1 : 1'b0;
//时序电路,用来给ad_to_vga_addr寄存器赋值
always @ (posedge posedge_reg or negedge RST_N)
begin
if(!RST_N) //判断复位
ad_to_vga_addr <= 1'b0; //初始化ad_to_vga_addr
else
ad_to_vga_addr <= ad_to_vga_addr_n;//给ad_to_vga_addr赋值
end
//组合电路,用于生成RAM_AD_TO_VGA的地址
always @ (*)
begin
if(ad_to_vga_addr < 16'd800) //判断地址
ad_to_vga_addr_n = ad_to_vga_addr + 1'b1;//地址累加
else
ad_to_vga_addr_n <= 0; //地址清零
end
//例化双口RAM_AD_TO_VGA模块
RAM_AD_TO_VGA AD_TO_VGA_Init
(
.wrclock (CLK_50M ), //写时钟
.wraddress (ad_to_vga_addr ), //写地址
.wren (posedge_reg ), //写使能
.data (10'd255 - in_ad_data), //写数据
.rdclock (CLK_40M ), //读时钟
.rdaddress (vga_x - 16'd100 ), //读地址
.q (ad_to_vga_data ) //读数据
);
//时序电路,用来给ad_to_vga_addr寄存器赋值
always @ (posedge posedge_reg or negedge RST_N)
begin
if(!RST_N) //判断复位
ad_to_fft_addr <= 1'b0; //初始化ad_to_fft_addr
else
ad_to_fft_addr <= ad_to_fft_addr_n;//给ad_to_fft_addr赋值
end
//组合电路,用于生成RAM_AD_TO_FFT的地址
always @ (*)
begin
if(ad_to_fft_addr < 16'd256) //判断地址
ad_to_fft_addr_n = ad_to_fft_addr + 1'b1;//地址累加
else
ad_to_fft_addr_n <= 0; //地址清零
end
//例化双口RAM_AD_TO_FFT模块
RAM_AD_TO_FFT AD_TO_FFT_Init
(
.wrclock (CLK_50M ), //写时钟
.wraddress (ad_to_fft_addr ), //写地址
.wren (posedge_reg ), //写使能
.data (in_ad_data ), //写数据
.rdclock (CLK_50M ), //读时钟
.rdaddress (fft_bit_cnt ), //读地址
.q (ad_to_fft_data ) //读数据
);
//时序电路,用来给time_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
time_cnt <= 27'h0; //初始化time_cnt值
else
time_cnt <= time_cnt_n; //用来给time_cnt赋值
end
//组合电路,实现1s的定时计数器
always @ (*)
begin
if(time_cnt == SET_TIME_1S) //判断1s时间
time_cnt_n = 27'h0; //如果到达1s,定时计数器将会被清零
else
time_cnt_n = time_cnt + 27'h1; //如果未到1s,定时计数器将会继续累加
end
//时序电路,用来给fft_rst_flag寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N) //判断复位
fft_rst_flag <= 1'b0; //初始化fft_rst_flag值
else
fft_rst_flag <= fft_rst_flag_n; //用来给fft_rst_flag赋值
end
//组合电路,用来生成FFT模块复位标志位
always @ (*)
begin
if(time_cnt == SET_TIME_1S) //判断时间
fft_rst_flag_n = 1'b0; //FFT模块复位标志位置0
else
fft_rst_flag_n = 1'b1; //FFT模块复位标志位置1
end
//例化FFT控制模块
FFT_Control_Module FFT_Control_Init
(
.CLK_50M (CLK_50M ), //时钟端口,开发板用的50M晶振
.RST_N (fft_rst_flag ), //FFT模块复位标志位
.data_real_in_int (ad_to_fft_data ), //FFT中用到的AD数据
.fft_real_out_int (fft_real_out_int ), //FFT实数的输出
.fft_imag_out_int (fft_imag_out_int ), //FFT虚数的输出
.fft_bit_cnt (fft_bit_cnt ), //FFT位计数器
.vga_fengzhi (vga_fengzhi ) //VGA中显示的峰峰值
);
endmodule