以下为仿真顶层模块的设计
001 `timescale 1ns/1ns
002 `include "../rtl/header.v"
003 module uart_scope_tb;
004 localparam KEY_WIDTH = 3;
005
006 reg Clk;
007 reg Rst_n;
008 reg [KEY_WIDTH - 1:0]Key_in;
009
010 reg ADC_Din;
011 wire ADC_Clk;
012 wire ADC_Cs_n;
013
014 /*波特率设置总线,此处默认为9600bps,仿真不做波特率修改测试*/
015 wire [2:0]Baud_Set;
016 reg [7:0]Tx_Data;/*串口发送仿真模型待发送数据字节*/
017 reg Tx_En; /*串口发送仿真模型发送使能信号*/
018 wire Rs232_MTSR; /*串口“主机(PC)发送-从机(FPGA)接收”信号*/
019 wire Rs232_MRST; /*串口“主机(PC)接收-从机(FPGA)发送”信号*/
020 wire Tx_Done; /*串口字节发送完成信号*/
021
022 assign Baud_Set = 3'd0;/*设置波特率为固定的9600bps*/
023
024 localparam
025 Header = 8'hAA, /*帧头*/
026 Length = 8'd3, /*帧长*/
027 Tail = 8'h88; /*帧尾*/
028
029 /*------例化串口示波器顶层模块------*/
030 uart_scope uart_scope(
031 .Clk(Clk),
032 .Rst_n(Rst_n),
033 .Rs232_Rx(Rs232_MTSR),
034 .Rs232_Tx(Rs232_MRST),
035 .Key_in(Key_in),
036 .ADC_Din(ADC_Din),
037 .ADC_Clk(ADC_Clk),
038 .ADC_Cs_n(ADC_Cs_n)
039 );
040
041 /*------例化串口发送仿真模型------*/
042 Uart_Tx_Model Uart_Tx_Model(
043 .Baud_Set(Baud_Set),
044 .Tx_Data(Tx_Data),
045 .Tx_En(Tx_En),
046 .uart_tx(Rs232_MTSR),
047 .Tx_Done(Tx_Done)
048 );
049
050 /*------例化串口接收仿真模型------*/
051 //该模型接收FPGA发送出来的数据并打印在modelsim的transcript窗口中
052 Uart_RX_Model Uart_RX_Model(
053 .Baud_Set(Baud_Set),
054 .uart_rx(Rs232_MRST)
055 );
056
057 /*-------生成50M时钟信号--------*/
058 initial Clk = 0;
059 always #10 Clk = ~Clk;
060
061 /*-------生成ADC_Din数据-------*/
062 /*此处不对ADC的采样结果多做计较,只要求保
063 证ADC_Din上有数据即可,有兴趣者可自己编写仿真模型*/
064 initial ADC_Din = 1;
065 always #1315 ADC_Din = ~ADC_Din;
066
067 initial begin
068 Rst_n = 1'b0;
069 Tx_En = 1'b0;
070 Tx_Data = 8'd0;
071 Key_in = 4'b1111;
072 #200;
073 Rst_n = 1'b1; /*释放复位信号,系统即进入正常工作状态*/
074 #1000;
075 En_DDS_Run; /*使能DDS信号发生器生成信号数据*/
076 #10000;
077 En_S_DDS; /*使能采样ADC数据*/
078 En_S_ADC; /*使能采样DDS数据*/
079 #10000;
080 En_UART_Send;/*使能串口发送,此时串口猎人软件上将会开始持续接收到数据*/
081 end
082
083 initial begin
084 #200_000_000;press_key(0);
085 #200_000_000;press_key(1);
086 #200_000_000;
087 $stop;
088 end
089
090
091
092 /*---发送命令帧数据任务-----*/
093 task Send_CMD;
094 input [7:0]DATAA,DATAB,DATAC;/*用户数据(地址、数据高字节,数据低字节)*/
095 begin
096 Tx_Data = Header;/*需发送数据为帧头*/
097 Tx_En = 1; /*启动发送*/
098 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
099 @(posedge Tx_Done)/*等待发送完成信号*/
100 #1000;
101
102 Tx_Data = Length;/*需发送数据为帧长,此处帧长只是数据内容的长度*/
103 Tx_En = 1; /*启动发送*/
104 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
105 @(posedge Tx_Done)/*等待发送完成信号*/
106 #1000;
107
108 Tx_Data = DATAA;/*需发送数据第一个字节,此数据代表外设寄存器的地址*/
109 Tx_En = 1; /*启动发送*/
110 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
111 @(posedge Tx_Done)/*等待发送完成信号*/
112 #1000;
113
114 Tx_Data = DATAB;/*需发送数据第二个字节,此数据代表写入外设寄存器的内容高8位*/
115 Tx_En = 1; /*启动发送*/
116 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
117 @(posedge Tx_Done)/*等待发送完成信号*/
118 #1000;
119
120 Tx_Data = DATAC;/*需发送数据第三个字节,此数据代表写入外设寄存器的内容低8位*/
121 Tx_En = 1; /*启动发送*/
122 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
123 @(posedge Tx_Done)/*等待发送完成信号*/
124 #1000;
125
126 Tx_Data = Tail;/*需发送数据为帧尾*/
127 Tx_En = 1; /*启动发送*/
128 #20 Tx_En = 0; /*一个时钟周期后,清零发送启动信号*/
129 @(posedge Tx_Done)/*等待发送完成信号*/
130 #1000;
131 #10000;
132 end
133 endtask
134
135 task En_DDS_Run;/*使能DDS生成数据*/
136 begin
137 Send_CMD(`DDS_En, 8'h00, 8'h01);
138 $display("En DDS Run");
139 end
140 endtask
141
142 task Stop_DDS_Run;/*停止DDS生成数据*/
143 begin
144 Send_CMD(`DDS_En, 8'h00, 8'h00);
145 $display("Stop DDS Run");
146 end
147 endtask
148
149 task En_S_DDS;/*使能采样DDS数据*/
150 begin
151 Send_CMD(`DDS_Sample_En, 8'h00, 8'h01);
152 $display("En Sample DDS data");
153 end
154 endtask
155
156 task Stop_S_DDS;/*停止采样DDS数据*/
157 begin
158 Send_CMD(`DDS_Sample_En, 8'h00, 8'h00);
159 $display("Stop Sample DDS data");
160 end
161 endtask
162
163 task En_UART_Send;/*使能串口发送*/
164 begin
165 Send_CMD(`UART_En_Tx, 8'h00, 8'h01);
166 $display("En UART Send");
167 end
168 endtask
169
170 task Stop_UART_Send;/*停止串口发送*/
171 begin
172 Send_CMD(`UART_En_Tx, 8'h00, 8'h00);
173 $display("Stop UART Send");
174 end
175 endtask
176
177 task En_S_ADC;/*使能采集ADC数据*/
178 begin
179 Send_CMD(`ADC_Sample_En, 8'h00, 8'h01);
180 $display("En Sample ADC data");
181 end
182 endtask
183
184 task Stop_S_ADC;/*停止采集ADC数据*/
185 begin
186 Send_CMD(`ADC_Sample_En, 8'h00, 8'h00);
187 $display("Stop Sample ADC data");
188 end
189 endtask
190
191 task Set_ADC_Sample_Speed;/*设置ADC采样率*/
192 input[25:0] Fs;/*采样率实际频率*/
193 reg [31:0] S_cnt_top;/*分频计数器计数最大值*/
194 begin
195 /*由采样实际频率值换算出采样分频计数器计数最大值*/
196 S_cnt_top = 50000000/Fs - 1;
197 /*写采样分频计数器计数最大值低16位*/
198 Send_CMD(`ADC_S_Cnt_Max_L,S_cnt_top[15:8],S_cnt_top[7:0]);
199 /*写采样分频计数器计数最大值高16位*/
200 Send_CMD(`ADC_S_Cnt_Max_H,S_cnt_top[31:24],S_cnt_top[23:16]);
201 $display("Set ADC Sample Speed as = %0d" ,Fs);
202 end
203 endtask
204
205 task Set_DDS_Sample_Speed;/*设置DDS数据的采样率*/
206 input[25:0] Fs;/*采样率实际频率*/
207 reg [31:0] S_cnt_top;/*分频计数器计数最大值*/
208 begin
209 /*由采样实际频率值换算出采样分频计数器计数最大值*/
210 S_cnt_top = 50000000/Fs - 1;
211 /*写采样分频计数器计数最大值低16位*/
212 Send_CMD(`DDS_S_Cnt_Max_L,S_cnt_top[15:8],S_cnt_top[7:0]);
213 /*写采样分频计数器计数最大值高16位*/
214 Send_CMD(`DDS_S_Cnt_Max_H,S_cnt_top[31:24],S_cnt_top[23:16]);
215 $display("Set DDS Sample Speed as = %0d" ,Fs);
216 end
217 endtask
218
219 task Set_DDS_Fout_Speed;/*设置DDS输出信号频率*/
220 input[25:0] Fs;/*输出信号实际频率*/
221 reg [31:0] r_fword;/*DDS频率控制字*/
222 begin
223 /*由实际要求输出频率数据换算出频率控制字*/
224 r_fword = Fs*65536*65536/50000000;
225 Send_CMD(`DDS_Fword_L,r_fword[15:8],r_fword[7:0]);
226 Send_CMD(`DDS_Fword_H,r_fword[31:24],r_fword[23:16]);
227 $display("Set DDS Fout as = %0d" ,Fs);
228 end
229 endtask
230
231
232 task press_key;
233 input [KEY_WIDTH/2:0]Key;
234 reg [15:0]myrand;
235 begin
236 Key_in = {KEY_WIDTH{1'b1}};
237 /*按下抖动*/
238 repeat(20)begin
239 myrand = {$random} % 65536;
240 #myrand Key_in[Key] = ~Key_in[Key];
241 end
242 Key_in[Key] = 1'b0;
243
244 #22000000;/*稳定期*/
245
246 /*释放抖动*/
247 repeat(20)begin
248 myrand = {$random} % 65536;
249 #myrand Key_in[Key] = ~Key_in[Key];
250 end
251 Key_in[Key] = 1'b1;
252 #22000000;/*稳定期*/
253 end
254 endtask
255
256 endmodule
下图为系统仿真架构图:
这里,在我们提供的工程中,已经设置好了Nativelink,用户只需要在QuartusII中点击tools—run rtl simulation tool—rtl simulation即可自动调用modelsim-altera并执行仿真,因为这里完全模拟真实时序进行仿真,因此运行完整个仿真大约需要5—10分钟。
仿真完成后,结果如图所示:
其中,Rx_Byte为串口接收仿真模型接收到的数据,这里以波形的方式展示。ADC_Data为ADC采样结果,DDS_Data为DDS输出的数据最下方为按键标志和按键结果,当按下按键1时,数据通道切换为ADC的采样结果,当按下按键2时,数据通道切换为DDS的输出数据。
(如果用户在进行仿真的过程中发现仿真无法运行,在modelsim中提示错误的话,请删除simulation—>modelsim文件夹下除wave.do和mydo.do文件外的其他所有文件,然后在quartus 中重新启动仿真)
小梅哥
2015年4月8日 于至芯科技