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

相關文章
相關標籤/搜索