FPGA之UART回传数据篇(2)

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
data_genertor

接收模块:调试

`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
View Code

发送模块: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
View Code

顶层模块:(将发送的数据再回环到接收,查看数据是不是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
View Code

仿真测试: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
View Code

 

 

 

上板子测试:ip

 

 

 

 

 

总结:

可利用串口返回数值,来为之后调试手段添砖加瓦,后面可直接利用移植时,只需将data_gen部分替换便可

相关文章
相关标签/搜索