1 //此代码的注意事项,首先这个代码不能仿真成功会出现一定的时间延迟,
  2 //因为在做板级验证的时候把时间改成了100ms发送一次,要想仿真成功,把时间改成499999
  3 //使用上一节课设计的发送模块,设计一个数据发送器,
  4 //每10ms以115200的波特率发送一个数据,每次发送的
  5 //数据比前一个数据大一(计数器)
  6 //首先是发送八位数据的uart_byte_tx的更改的源代码
  7 
  8 //1、这里我使用的是(uart_p==uart_byte_tx)
  9 //这两个是底层模块
 10 
 11 module uart_p(
 12     clk,
 13     reset_n,
 14     send_go,
 15     data,
 16     baud_set,
 17     uart_tx,
 18     tx_done
 19     );
 20     input clk;
 21     input reset_n;
 22     input send_go;
 23     input [7:0] data;
 24     input [2:0]baud_set;
 25     output reg uart_tx;
 26     output reg tx_done;
 27     //书写不同波特率对应的模式
 28     reg [17:0] bps_DR;
 29     always@(*)
 30         case(baud_set)
 31             0:bps_DR=50000000/9600;
 32             1:bps_DR=50000000/19200;
 33             2:bps_DR=50000000/38400;
 34             3:bps_DR=50000000/57600;
 35             4:bps_DR=50000000/115200;
 36             default:bps_DR=50000000/9600;
 37         endcase
 38     
 39     //被动式读取其他模块的数据
 40     reg send_en;
 41     always@(posedge clk or negedge reset_n)
 42     if(!reset_n)
 43         send_en<=0;
 44     else if(send_go)
 45         send_en<=1;
 46     else if(tx_done)
 47         send_en<=0;
 48         
 49         
 50     //书写关于data的寄存问题
 51     reg [7:0] r_data;
 52     always@(posedge clk)
 53     if(send_go)
 54         r_data<=data;
 55     else
 56         r_data<=r_data;
 57     
 58     //先写一个适合波特率的定时
 59     reg [17:0] div_cnt;
 60     always@(posedge clk or negedge reset_n)
 61     if(!reset_n)
 62         div_cnt<=0;
 63     else if(send_en)begin
 64         if(div_cnt==bps_DR-1)
 65             div_cnt<=0;
 66         else
 67             div_cnt<=div_cnt+1'b1;
 68     end
 69     else
 70         div_cnt<=0;
 71     wire bps_clk;//为什么改了位置就不出现问题了呢??????
 72     assign bps_clk=(div_cnt==1);//放在上面就不行,还跟位置有关系。
 73     //将时间拼接为11个时间段
 74     reg [3:0] bps_cnt;
 75     always@(posedge clk or negedge reset_n)
 76     if(!reset_n)
 77         bps_cnt<=0;
 78     else if(send_en)begin
 79         if(bps_clk)begin
 80             if(bps_cnt==11) 
 81                 bps_cnt<=0;
 82             else
 83                 bps_cnt<=bps_cnt+1'b1;
 84         end
 85     end
 86     else
 87         bps_cnt<=0;
 88     //这里一定要注意不加else bps_cnt<=0;因为条件是div_cnt==bps_DR-1,如果else就会出现bps_cnt一直为0的怪情况。
 89     
 90     always@(posedge clk or negedge reset_n)
 91     if(!reset_n)
 92         uart_tx<=1'b1;
 93     else case(bps_cnt)
 94             1:uart_tx<=0;
 95             2:uart_tx<=r_data[0];
 96             3:uart_tx<=r_data[1];
 97             4:uart_tx<=r_data[2];
 98             5:uart_tx<=r_data[3];
 99             6:uart_tx<=r_data[4];
100             7:uart_tx<=r_data[5];
101             8:uart_tx<=r_data[6];
102             9:uart_tx<=r_data[7];
103             10:uart_tx<=1;
104             11:uart_tx<=1;
105             default:uart_tx<=1;
106     endcase
107 
108     always@(posedge clk or negedge reset_n)
109     if(!reset_n)
110         tx_done<=0;
111     else if((bps_clk==1)&&(bps_cnt==10))
112         tx_done<=1;
113     else
114         tx_done<=0;
115 endmodule
116 
117 //2、uart_byte_tx_tb仿真代码(这里我使用的是uart_p_tb==uart_byte_tx_tb)
118 
119 `timescale 1ns / 1ns
120 module uart_p_tb();
121     reg clk;
122     reg reset_n;
123     reg send_en;
124     reg [7:0] data;
125     reg [2:0]baud_set;
126     wire uart_tx;
127     wire tx_done;
128     uart_p uart_p_inst0(
129     .clk(clk),
130     .reset_n(reset_n),
131     .send_en(send_en),
132     .data(data),
133     .baud_set(baud_set),
134     .uart_tx(uart_tx),
135     .tx_done(tx_done)
136 );
137     initial clk=1;
138     always #10 clk=~clk;
139     
140     initial begin 
141         reset_n=0;
142         send_en=0;
143         data=0;
144         baud_set=4;
145         #201;
146         reset_n=1;
147         #20;
148         
149         send_en=1;
150         data=8'h57;
151        
152         @(posedge tx_done)
153         send_en=0;
154         #2000;
155         send_en=1;
156         data=8'h75;
157         #20;
158         @(posedge tx_done)
159         send_en=0;
160         #200000;
161         $stop;
162     end
163 endmodule
164 
165 //3、uart_test仿真代码,这里面是顶层模块
166 
167 module uart_test(
168     clk,
169     reset_n,
170     uart_tx
171     );
172     input clk;
173     input reset_n;
174     output uart_tx;
175     
176     reg [26:0] counter;
177     reg send_go;
178     reg [7:0]data;
179     //先进行底层模块的例化
180     //例化只用写对应的端口和连接
181     uart_p uart_p_inst0(
182         .clk(clk),
183         .reset_n(reset_n),
184         .send_go(send_go),
185         .baud_set(3'd4),
186         .data(data),
187         .uart_tx(uart_tx),
188         .tx_done(tx_done)
189     );
190     //先书写10ms的定时器
191     
192     always@(posedge clk or negedge reset_n)
193     if(!reset_n)
194         counter<=0;
195     else if(counter==4999999)
196         counter<=0;
197     else
198         counter<=counter+1;
199     //开始书写发送信号send_en
200     
201     always@(posedge clk or negedge reset_n)
202     if(!reset_n)
203         send_go<=0;
204     else if(counter==1)
205         send_go<=1;
206     else
207         send_go<=0;
208     //为什么不管tx_done??????
209         
210     //开始书写发送的数据,让其执行每次加一的操作。
211     
212     always@(posedge clk or negedge reset_n)
213     if(!reset_n)
214         data<=0;
215     else if(tx_done)
216         data<=data+1'b1;
217 endmodule
218 
219 //4、uart_test_tb仿真代码,这里面是顶层模块
220 
221 `timescale 1ns / 1ps
222 module uart_test_tb();
223     reg clk;
224     reg reset_n;
225     wire uart_tx;
226     uart_test uart_test_inst0(
227     .clk(clk),
228     .reset_n(reset_n),
229     .uart_tx(uart_tx)
230     );
231     initial clk=1;
232     always#10 clk=~clk;
233     
234     initial begin
235         reset_n=0;
236         #201;
237         reset_n=1;
238         
239         #50000000;
240         $stop;
241     end
242     
243     
244 endmodule

 

posted on 2023-03-02 22:11  无情的造轮子  阅读(133)  评论(0编辑  收藏  举报