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