小梅哥课程学习——串口接收模块的项目应用案例(扳级验证,未出现结果,(可能其中代码有误未发现。),待处理)

发布时间 2023-03-27 22:23:45作者: 无情的造轮子
  1 //还没找到出错的原因
  2 //使用串口来控制LED的工作状态
  3 //使用串口发送指令到FPGA开发版,来控制第7课中第4个实验的开发版上的LED灯的工作状态。
  4 //让LED灯按照指定亮灭模式亮灭,亮灭模式未知,由用户随机指定。8个变换状态为1个循环,每个变化状态的时间值,可以根据不同的应用场景选择。
  5 //如何使用串口接收8个字节的数据
  6 //顶层模块,例化各个子模块。
  7 module uart_rx_ctrl_led(
  8     clk,
  9     reset_n,
 10     led,
 11     uart_rx
 12     );
 13     input clk;
 14     input reset_n;
 15     output led;
 16     input uart_rx;
 17     //顶层模块连接模块不需要考虑reg的事情
 18     //只有在顶层驱动信号的时候才需要定义reg
 19     
 20     wire [7:0] ctrl;
 21     wire [31:0] time_set;
 22     wire rx_done;
 23     wire [7:0] rx_data;
 24     //例化被控制的LED模块
 25     counter_led_4 counter_led_4_inst0(
 26         .clk(clk),
 27         .reset_n(reset_n),
 28         .Time(time_set),
 29         .ctrl(ctrl),
 30         .led(led)
 31 ); 
 32     //例化串口接收模块
 33     uart_byte_rx uart_byte_rx_inst0(
 34         .clk(clk),
 35         .reset_n(reset_n),
 36         .baud_set(4),
 37         .uart_rx(uart_rx),
 38         .data(rx_data),
 39         .rx_done(rx_done)
 40     );
 41     //实例化连接两个模块(串口接收模块和LED显示模块)的命令模块。
 42     uart_cmd uart_cmd_inst0(
 43         .clk(clk),
 44         .reset_n(reset_n),
 45         .rx_data(rx_data),
 46         .rx_done(rx_done),
 47         .ctrl(ctrl),
 48         .time_set(time_set)
 49     );
 50 endmodule
 51 
 52 //底层模块一uart_byte_rx
 53 //verilog无法实现542.5ns的定时,只能实现540ns,故而tx_done会提前到来。
 54 //不过没有关系,可以提前接收,但是不能滞后接收,
 55 //如果出现,就会出现丢数据的现象。
 56 `timescale 1ns / 1ns
 57 module uart_byte_rx(
 58     clk,
 59     reset_n,
 60     baud_set,
 61     uart_rx,
 62     data,
 63     rx_done
 64     );
 65     input clk;
 66     input reset_n;
 67     input [2:0] baud_set;
 68     input uart_rx;
 69     output reg [7:0]data;
 70     output reg rx_done;
 71     //通过定义两位寄存器来存储发送的状态。为之后的对比形成基础。
 72     reg [1:0]uart_rx_r;
 73     always@(posedge clk)begin
 74         uart_rx_r[0] <=  #1 uart_rx;
 75         uart_rx_r[1] <=  #1 uart_rx_r[0];
 76     end
 77     
 78 //    wire pedge_uart_rx;
 79 //    //前一时刻为0,新来的时刻为1,这样才产生了上升沿。
 80 ////    assign pedge_uart_rx=(uart_rx_r[1] == 0)&&(uart_rx_r[0] == 1);
 81 //    assign pedge_uart_rx=(uart_rx_r == 2'b01  );
 82     
 83     wire nedge_uart_rx;
 84     //前一时刻为1,新来的时刻为0,这样才产生了下降沿。
 85 //    assign nedge_uart_rx=((uart_rx_r[1]==1)&&(uart_rx_r[0]==0));
 86     assign nedge_uart_rx=(uart_rx_r==2'b10);
 87     reg[8:0]bps_DR;
 88     always@(*)
 89         case(baud_set)
 90             0:bps_DR = 1000000000/9600/16/20-1;
 91             1:bps_DR = 1000000000/19200/16/20-1;
 92             2:bps_DR = 1000000000/38400/16/20-1;
 93             3:bps_DR = 1000000000/57600/16/20-1;
 94             4:bps_DR = 1000000000/115200/16/20-1;
 95             default:bps_DR = 1000000000/9600/16/20-1;
 96         endcase
 97     wire bps_clk_16x;
 98     assign bps_clk_16x=(div_cnt == bps_DR/2);
 99     //设置发送控制信号rx_en
100     reg rx_en;
101     always@(posedge clk or negedge reset_n)
102     if(!reset_n)
103         rx_en <=  #1 0;
104     else if(nedge_uart_rx)
105         rx_en <=  #1 1;
106     else if(rx_done || sta_bit >= 4)
107         rx_en <=  #1 0;
108     //设置分频计数器的最小单元
109     reg [8:0] div_cnt;
110     always@(posedge clk or negedge reset_n)
111     if(!reset_n)
112         div_cnt <=  #1 0;
113     else if(rx_en)begin
114         if(div_cnt == bps_DR)
115             div_cnt <=  #1 0;
116         else
117             div_cnt <=  #1 div_cnt + 1'b1;
118     end
119     else
120         div_cnt <=  #1 0;
121     //采样数据
122     reg [7:0]bps_cnt;
123     always@(posedge clk or negedge reset_n)
124     if(!reset_n)
125         bps_cnt <=  #1 0;
126     else if(rx_en)begin
127         if(bps_clk_16x)begin
128             if(bps_cnt == 160)
129                 bps_cnt <=  #1 0;
130             else
131                 bps_cnt <=  #1 bps_cnt + 1'b1;;
132         end
133         else
134             bps_cnt <=  #1 bps_cnt;
135     end
136     else
137         bps_cnt <=  #1 0;
138     //接收数据
139     //二位数组reg width name number;
140     reg [7:0] r_data [7:0];
141     reg [2:0] sta_bit;
142     reg [2:0] sto_bit;
143     
144     always@(posedge clk or negedge reset_n)
145     if(!reset_n)begin
146         sta_bit <=  #1 0;
147         sto_bit <=  #1 0;
148         r_data[0] <=  #1 0;
149         r_data[1] <=  #1 0;
150         r_data[2] <=  #1 0;
151         r_data[3] <=  #1 0;
152         r_data[4] <=  #1 0;
153         r_data[5] <=  #1 0;
154         r_data[6] <=  #1 0;
155         r_data[7] <=  #1 0;
156     end
157     else if (bps_clk_16x)begin
158         case(bps_cnt)
159             0:begin
160                 sta_bit <=  #1 0;
161                 sto_bit <=  #1 0;
162                 r_data[0] <=  #1 0;
163                 r_data[1] <=  #1 0;
164                 r_data[2] <=  #1 0;
165                 r_data[3] <=  #1 0;
166                 r_data[4] <=  #1 0;
167                 r_data[5] <=  #1 0;
168                 r_data[6] <=  #1 0;
169                 r_data[7] <=  #1 0;
170             end
171             5,6,7,8,9,10,11:sta_bit <=  #1 sta_bit + uart_rx;
172             21,22,23,24,25,26,27: r_data[0] <=  #1 r_data[0] + uart_rx;
173             37,38,39,40,41,42,43: r_data[1] <=  #1 r_data[1] + uart_rx;
174             53,54,55,56,57,58,59: r_data[2] <=  #1 r_data[2] + uart_rx;
175             69,70,71,72,73,74,75: r_data[3] <=  #1 r_data[3] + uart_rx;
176             85,86,87,88,89,90,91: r_data[4] <=  #1 r_data[4] + uart_rx;
177             101,102,103,104,105,106,107:r_data[5] <=  #1 r_data[5] + uart_rx;
178             117,118,119,120,121,122,123:r_data[6] <=  #1 r_data[6] + uart_rx;
179             133,134,135,136,137,138,139:r_data[7] <=  #1 r_data[7] + uart_rx;
180             149,150,151,152,153,154,155:sto_bit <=  #1 sto_bit + uart_rx;
181             default:;
182         endcase
183     end
184     always@(posedge clk or negedge reset_n)
185     if(!reset_n)begin
186         data<=  #1 0;
187     end
188     else if(bps_clk_16x && bps_cnt==159)begin
189         data[0] <=  #1 (r_data[0] >= 4) ? 1:0;
190         data[1] <=  #1 (r_data[1] >= 4) ? 1:0;
191         data[2] <=  #1 (r_data[2] >= 4) ? 1:0;
192         data[3] <=  #1 (r_data[3] >= 4) ? 1:0;
193         data[4] <=  #1 (r_data[4] >= 4) ? 1:0;
194         data[5] <=  #1 (r_data[5] >= 4) ? 1:0;
195         data[6] <=  #1 (r_data[6] >= 4) ? 1:0;
196         data[7] <=  #1 (r_data[7] >= 4) ? 1:0;
197     end
198     always@(posedge clk or negedge reset_n)
199     if(!reset_n)
200         rx_done<=  #1 0;
201     else if((div_cnt == bps_DR/2) && bps_cnt == 160)
202         rx_done <=  #1 1;
203     else
204         rx_done <=  #1 0;
205 endmodule
206 
207 //底层模块二uart_cmd
208 
209 `timescale 1ns / 1ns
210 module uart_cmd(
211     clk,
212     reset_n,
213     rx_data,
214     rx_done,
215     ctrl,
216     time_set
217     );
218     input clk;
219     input reset_n;
220     input [7:0] rx_data;
221     input rx_done;
222     output reg [7:0] ctrl;
223     output reg[31:0] time_set;
224     
225     reg [7:0] data_str [7:0];
226     always@(posedge clk)
227     //循环移位接收数据,每来一次rx_done,接收一次数据。
228     if(rx_done)begin
229         data_str[7] <= #1 rx_data;
230         data_str[6] <= #1 data_str[7];
231         data_str[5] <= #1 data_str[6];
232         data_str[4] <= #1 data_str[5];
233         data_str[3] <= #1 data_str[4];
234         data_str[2] <= #1 data_str[3];
235         data_str[1] <= #1 data_str[2];
236         data_str[0] <= #1 data_str[1];
237     end   
238     //判断每位数据是否是所发送的8比特数据,
239     //判断M0,M1,M7是否如自定义的数据一样。
240     reg r_rx_done;
241     always@(posedge clk)
242         r_rx_done <= rx_done;
243         
244         
245     always@(posedge clk or negedge reset_n)
246     if(!reset_n)begin
247         ctrl <= #1 0;
248         time_set <= #1 0;
249     end
250     else if(r_rx_done)begin
251         if((data_str[0]==8'h55) && (data_str[1]==8'hA5) && (data_str[7]==8'hF0))begin
252            time_set[7:0] <= #1  data_str[2];
253            time_set[15:8] <= #1  data_str[3];
254            time_set[23:16] <= #1  data_str[4];
255            time_set[31:24] <= #1  data_str[5];
256            ctrl <= #1 data_str[6];
257         end
258         
259     end
260 endmodule
261 
262 //底层模块三counter_led_4
263 
264 //可能是led出现了问题
265 `timescale 1ns / 1ns
266 module counter_led_4(
267     clk,
268     reset_n,
269     Time,
270     ctrl,
271     led
272 );
273     input clk;
274     input reset_n;
275     input [31:0] Time;
276     input [7:0] ctrl;
277     output reg led;
278     reg [31:0] counter;
279     always@(posedge clk or negedge reset_n)
280         if(!reset_n)
281             counter <= #1 0;
282 //波形出现Time=0的情况,上电的时候,counter==0-1发现不满足
283 //,就一直自加,直到加到32'hFFFF FFFF.
284 //前面接收发送数据用的时间过长,导致Time值大于25000000,直到
285 //32位计数满了之后才继续进行。
286         else if(counter >= Time-1)
287             counter <= #1 0;
288         else
289             counter <= #1 counter + 1'b1;
290     reg [2:0] counter2;
291     always@(posedge clk or negedge reset_n)
292         if(!reset_n)
293             counter2 <= #1 0;
294         else if(counter == Time-1)//一旦超过范围值就清零
295             counter2 <= #1 counter2 + 1'b1;
296      
297         always@(posedge clk or negedge reset_n)
298         if(!reset_n)
299             led <= #1 0;
300         else case(counter2)
301             0:led <= #1 ctrl[0];
302             1:led <= #1 ctrl[1];
303             2:led <= #1 ctrl[2];
304             3:led <= #1 ctrl[3];
305             4:led <= #1 ctrl[4];
306             5:led <= #1 ctrl[5];
307             6:led <= #1 ctrl[6];
308             7:led <= #1 ctrl[7];
309             default:led <= #1 led;
310         endcase
311 endmodule
312 
313 
314 //仿真文件
315 `timescale 1ns / 1ps
316 module uart_rx_ctrl_led_tb();
317     reg clk;
318     reg reset_n;
319     wire led;
320     reg uart_rx;
321     uart_rx_ctrl_led uart_rx_ctrl_led_inst0(
322         .clk(clk),
323         .reset_n(reset_n),
324         .led(led),
325         .uart_rx(uart_rx)
326     );
327 
328     initial clk = 1;
329     always#10 clk = !clk;
330     
331     initial begin
332         reset_n = 0;
333         uart_rx = 1;
334         #201;
335         reset_n = 1;
336         #200;
337         uart_tx_byte(8'h55);
338 //        @(posedge rx_done);
339         #90000;
340         uart_tx_byte(8'ha5);
341 //        @(posedge rx_done);
342         #90000;
343         uart_tx_byte(8'h40);
344         #90000;
345         uart_tx_byte(8'h78);
346         #90000;
347         uart_tx_byte(8'h7D);
348         #90000;
349         uart_tx_byte(8'h01);
350         #90000;
351         uart_tx_byte(8'hAA);
352         #90000;
353         uart_tx_byte(8'hF0);
354         #90000;
355         
356         
357         
358         uart_tx_byte(8'h55);
359 //        @(posedge rx_done);
360         #90000;
361         uart_tx_byte(8'ha5);
362 //        @(posedge rx_done);
363         #90000;
364         uart_tx_byte(8'h9a);
365         #90000;
366         uart_tx_byte(8'h78);
367         #90000;
368         uart_tx_byte(8'h56);
369         #90000;
370         uart_tx_byte(8'h34);
371         #90000;
372         uart_tx_byte(8'h12);
373         #90000;
374         uart_tx_byte(8'hf1);
375         #90000;
376         $stop;
377     end
378     
379     //新语法
380     task uart_tx_byte;
381         input [7:0]tx_data;
382         begin
383             uart_rx = 1;
384             #20;
385             uart_rx = 0;
386             #8680;
387             uart_rx = tx_data[0];
388             #8680;
389             uart_rx = tx_data[1];
390             #8680;
391             uart_rx = tx_data[2];
392             #8680;
393             uart_rx = tx_data[3];
394             #8680;
395             uart_rx = tx_data[4];
396             #8680;
397             uart_rx = tx_data[5];
398             #8680;
399             uart_rx = tx_data[6];
400             #8680;
401             uart_rx = tx_data[7];
402             #8680;
403             uart_rx=1;
404             #8680;
405         end
406     endtask
407 
408 endmodule
2023-03-27 22:17:29