PC發送寄存器值,FPGA經過串口返回一些值,能夠是FPGA狀態值,
能夠是須要讀的某個寄存器的值,本本實驗中,只返回一些固定值
下面經過,返回兩首首打油詩爲例,該部分能夠替換其餘,所以有高移植性html
能夠利用上一篇《FPGA之UART簡單通訊》的接收部分,而後發送模塊稍做修改便可。增長一個ram
分別放置不一樣數據,ide
coe1文件存儲數據以下:測試
B3, FA, BA, CC, C8,D5, B5, B1, CE, E7,
BA, B9, B5, CE, BA,CC, CF, C2, CD, C1,
CB, AD, D6, AA, C5,CC, D6, D0, B2, CD, 0A ,
C1, A3, C1, A3, BD,D4, D0, C1, BF, E0, 0A; spa
數據產生模塊:debug
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/09/23 10:37:17 // Design Name: // Module Name: data_genertor // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module data_genertor( input clk_125m, input [7:0] uart_rx_data, input uart_rx_valid, input [15:0] bit_num, (*mark_debug="true"*) output [7:0] uart_tx_data, (*mark_debug="true"*) output uart_tx_valid ); /*data_genertor0 your_instance_name ( .clka(clka), // input wire clka .ena(ena), // input wire ena .addra(addra), // input wire [6 : 0] addra .douta(douta) // output wire [7 : 0] douta );*/ //定義波特率 parameter BAUD_DIV = 14'd1086 ;//125/115200 parameter BAUD_MID = 14'd543 ;//DIV/2中間採樣點 reg en_a0 = 0; reg en_a0_r0 = 0; reg en_a0_r1 = 0; reg en_a1 = 0; (*mark_debug="true"*)reg [5:0] addra_r0; reg [6:0] addra_r1; reg baud_bps = 0; reg [13:0] baud_div = 0; reg send_en = 0; always@(posedge clk_125m )begin if(baud_div==BAUD_MID )begin baud_bps<= 1'b1; baud_div <= baud_div +1'b1; end else if(baud_div<BAUD_DIV )begin baud_bps<= 1'b0; baud_div <= baud_div +1'b1; end else begin baud_bps <= 0; baud_div <= 0; end end always@(posedge clk_125m)begin if (uart_rx_valid) case (uart_rx_data) 8'h6e: begin en_a0 <= 1'b1; en_a1 <= 1'b0; end 8'hAB: begin en_a0 <= 1'b0; en_a1 <= 1'b1; end 8'h00: begin en_a0 <= 1'b0; en_a1 <= 1'b0; end endcase else begin en_a0 <= 1'b0; en_a1 <= 1'b0; end end //send_en 接收有效值拉高,地址寫完拉低 always@(posedge clk_125m)begin if(addra_r0 == 6'd51) send_en <= 0; else if(uart_rx_valid==1'b1) send_en <= 1; else send_en <= send_en; end //addra_r0 always@(posedge clk_125m)begin if(send_en==1'b1)begin if(bit_num==16'd10) addra_r0 <= addra_r0 +1'b1; //每寫完一幀(start+8bit+stop)地址加一 else if (en_a0==1'b1 && bit_num==16'd10) addra_r0 <= addra_r0 +1'b1;//開始時,須要激化地址累加,不然bit_num沒法累加(參考tx模塊裏的 uart_tx_en_i ) else addra_r0 <=addra_r0; end else addra_r0 <= 0; end //uart_tx_en_i reg tx_en; reg tx_enr0; reg tx_enr1; always@(posedge clk_125m)begin if(send_en ==1'b1 && bit_num==16'd10) tx_en <= 1'b1; else tx_en <= 1'b0; end //打一拍 保持與數據沿對齊 always@(posedge clk_125m)begin tx_enr0 <= tx_en; tx_enr1 <= tx_enr0; en_a0_r0 <= en_a0; en_a0_r1 <= en_a0_r0; end assign uart_tx_valid = en_a0_r1||tx_enr1; data_genertor0 u_data_genertor0 ( .clka(clk_125m), // input wire clka .ena(send_en), // input wire ena[clk en] .addra(addra_r0), // input wire [6 : 0] addra .douta(uart_tx_data) // output wire [7 : 0] douta ); endmodule
接收模塊:調試
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/09/21 13:51:32 // Design Name: // Module Name: UART_RX // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module uart_rx_path( input clk_100m, input uart_rx_i, output [7:0] uart_rx_data_o, output uart_rx_done, output baud_bps_sim ); parameter [13:0] BAUD_DIV = 14'd868 ;// 14'd13020; //115200bps ,100Mhz parameter [13:0] BAUD_DIV_MID= 14'd434; //collection mid (*mark_debug="true"*) reg [13:0] baud_div =0; (*mark_debug="true"*) reg baud_bps =0; (*mark_debug="true"*) reg bps_start =0; always @(posedge clk_100m) begin if(baud_div==BAUD_DIV_MID)begin baud_bps<= 1'b1; baud_div<= baud_div +1'b1; end else if(baud_div<BAUD_DIV && bps_start)begin//當波特率啓動時,計數器累加 baud_div <= baud_div +1'b1; baud_bps <= 0; end else begin baud_bps<=0; baud_div<=0; end end (*mark_debug="true"*) reg [4:0] uart_rx_i_r = 5'b11111; always @(posedge clk_100m) begin uart_rx_i_r <= {uart_rx_i_r[3:0],uart_rx_i}; end wire uart_rx_int = uart_rx_i_r[4]|uart_rx_i_r[3]|uart_rx_i_r[2]|uart_rx_i_r[1]|uart_rx_i_r[0]; (*mark_debug="true"*) reg[3:0] bit_num = 0; (*mark_debug="true"*) reg uart_rx_done_r =0; (*mark_debug="true"*) reg state =1'b0; (*mark_debug="true"*) reg [7:0] uart_rx_data_0_r0 = 0; //process reg [7:0] uart_rx_data_0_r1 = 0; //done always @(posedge clk_100m) begin uart_rx_done_r <= 1'b0; case (state) 1'b0: if(!uart_rx_int)begin bps_start<=1'b1; state<=1'b1; end 1'b1: if(baud_bps) begin bit_num<=bit_num+1'b1; //有疑問 if(bit_num<4'd9) //有疑問 uart_rx_data_0_r0[bit_num-1]<= uart_rx_i; //else //uart_rx_data_0_r0 <= uart_rx_data_0_r0; end else if (bit_num==4'd10)begin bit_num <= 0; uart_rx_done_r <= 1'b1; uart_rx_data_0_r1 <= uart_rx_data_0_r0; state<=1'b0;//進入狀態0,再次循環檢測 bps_start<=0; end default:; endcase end assign baud_bps_tb=baud_bps;//for simulation assign uart_rx_data_o=uart_rx_data_0_r1; assign uart_rx_done=uart_rx_done_r; endmodule
發送模塊:code
module uart_tx_path( input clk_i, input [7:0] uart_tx_data_i, //待發送數據 input uart_tx_en_i, //發送發送使能信號 output [15:0] bit_num_w, output uart_tx_o ); parameter BAUD_DIV = 14'd868;//波特率時鐘,9600bps,100Mhz/9600=10416,波特率可調 parameter BAUD_DIV_CAP = 14'd434;//波特率時鐘中間採樣點,100Mhz/9600/2=d208,波特率可調 (*mark_debug="true"*)reg [13:0] baud_div=0; //波特率設置計數器 (*mark_debug="true"*)reg baud_bps=0; //數據發送點信號,高有效 reg [9:0] send_data=10'b1111111111;//待發送數據寄存器,1bit起始信號+8bit有效信號+1bit結束信號 (*mark_debug="true"*)reg [15:0] bit_num=0; //發送數據個數計數器 (*mark_debug="true"*)reg uart_send_flag=0; //數據發送標誌位 (*mark_debug="true"*)reg uart_tx_o_r=1; //發送數據寄存器,初始狀態位高 always@(posedge clk_i) begin if(baud_div==BAUD_DIV_CAP) //當波特率計數器計數到數據發送中點時,產生採樣信號baud_bps,用來發送數據 begin baud_bps<=1'b1; baud_div<=baud_div+1'b1; end else if(baud_div<BAUD_DIV && uart_send_flag)//數據發送標誌位有效期間,波特率計數器累加,以產生波特率時鐘 begin baud_div<=baud_div+1'b1; baud_bps<=0; end else begin baud_bps<=0; baud_div<=0; end end always@(posedge clk_i) begin if(uart_tx_en_i) //接收數據發送使能信號時,產生數據發送標誌信號 begin uart_send_flag<=1'b1; send_data<={1'b1,uart_tx_data_i,1'b0};//待發送數據寄存器裝填,1bit起始信號0+8bit有效信號+1bit結束信號 end else if(bit_num==16'd10) //發送結束時候,清楚發送標誌信號,並清楚待發送數據寄存器內部信號 begin uart_send_flag<=1'b0; send_data<=10'b1111_1111_11; end end always@(posedge clk_i) begin if(uart_send_flag) //發送有效時候 begin if(baud_bps)//檢測發送點信號 begin if(bit_num<=4'd10) begin uart_tx_o_r<=send_data[bit_num]; //發送待發送寄存器內數據,從低位到高位 bit_num<=bit_num+1'b1; end end else if(bit_num==15'd10) bit_num<=4'd0; end else begin uart_tx_o_r<=1'b1; //空閒狀態時,保持發送端位高電平,以備發送時候產生低電平信號 bit_num<=0; end end assign uart_tx_o=uart_tx_o_r; assign bit_num_w = bit_num; endmodule
頂層模塊:(將發送的數據再回環到接收,查看數據是不是ROM中的數據)htm
module uart_top( input clk_i_p, input clk_i_n, //input clk_i, input uart_rx_i, output uart_tx_o ); wire [7:0] uart_rx_data_o; wire [15:0] bit_num; wire [7:0] uart_tx_data; wire uart_tx_valid; wire uart_rx_done; wire clk_i; // IBUFDS IBUFDS_inst ( // .O(clk_i), // 1-bit output: Buffer output // .I(clk_i_p), // 1-bit input: Diff_p buffer input (connect directly to top-level port) // .IB(clk_i_n) // 1-bit input: Diff_n buffer input (connect directly to top-level port) // ); clk_wiz_0 clk_wiz_0_u ( // Clock out ports .clk_out1(clk_i), // output clk_out1 // Clock in ports .clk_in1_p(clk_i_p), // input clk_in1_p .clk_in1_n(clk_i_n)); // input clk_in1_n uart_rx_path uart_rx_path_u ( .clk_100m(clk_i), .uart_rx_i(uart_rx_i), .uart_rx_data_o(uart_rx_data_o), .uart_rx_done(uart_rx_done) ); uart_rx_path uart_rx_path_u0 ( .clk_100m(clk_i), .uart_rx_i(uart_tx_o), .uart_rx_data_o(), .uart_rx_done() ); data_genertor u_data_genertor( .clk_125m(clk_i), .uart_rx_data(uart_rx_data_o), .uart_rx_valid(uart_rx_done), .bit_num(bit_num), .uart_tx_data(uart_tx_data), .uart_tx_valid(uart_tx_valid) ); uart_tx_path uart_tx_path_u ( .clk_i(clk_i), .uart_tx_data_i(uart_tx_data), .bit_num_w (bit_num), .uart_tx_en_i(uart_tx_valid), .uart_tx_o(uart_tx_o) ); endmodule
仿真測試:blog
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/09/21 13:55:20 // Design Name: // Module Name: uart_top_tb // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module uart_top_TB; reg clk_i_p; reg clk_i_n; reg rst_n_i; reg uart_rx_i; wire [7:0] uart_tx_o; uart_top u_uart_top ( .clk_i_p (clk_i_p), .clk_i_n (clk_i_n), //.rst_n_i (rst_n_i), .uart_rx_i (uart_rx_i), .uart_tx_o (uart_tx_o) ); initial begin clk_i_p = 0; clk_i_n = 1; rst_n_i = 0; uart_rx_i = 1'b1; // Wait 100 ns for global reset to finish #96; rst_n_i=1; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0;//start //0110_1110 #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1;//stop #808320 //00000101 uart_rx_i = 1'b0;//start #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1;//stop #808320 //10000100 uart_rx_i = 1'b0;//start #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b0; #8680 uart_rx_i = 1'b1; #8680 uart_rx_i = 1'b1;//stop end always begin #2 clk_i_p = ~clk_i_p; #2 clk_i_n = ~clk_i_n; end endmodule
上板子測試:ip
總結:
可利用串口返回數值,來爲之後調試手段添磚加瓦,後面可直接利用移植時,只需將data_gen部分替換便可