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部分替换便可