我是靠谱客的博主 感动哈密瓜,最近开发中收集的这篇文章主要介绍实现上位机与FPGA uart交互,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言  初学者学习记录

目的:实现上位机与FPGA uart交互

开发环境:quatus prime 18.1,芯片 altera :EP4CE15F23C8。
实验现象:
1.使用uart:bps=9600(参数可调整),8n1数据结构发送和接收数据。
2.上位机与FPGA 64位数据通讯,16bit head+16地址(最高位0:写;1:读)+32数据。
3.  驱动数据参考下图 《regtable_uartledseg》

 RTL Viewer:

说明

1.uart串口接收数据8n1,将接收到的8位数据,串并转换为64位,经过译码器,驱动led和数码管。

2.读取led和数码管时,译码器的64位数据,经并串转换为8位数据,经uart发送。

代码见如下链接。

顶层文件:

module top_cfg_uart_led_seg(
    clk    ,
    rst_n  ,
    rx     ,
    tx     ,
    led    ,
    seg_sel,
    segment
);

input            clk    ;
input            rst_n  ;
input            rx     ;
output           tx     ;
output[ 3:0]     led    ;
output[ 7:0]     seg_sel;
output[ 7:0]     segment;

`include "../src/cfgctrl/uart_ledseg_wire.v"

wire  [63:0]     cfgCtrl_dout;
wire             cfgCtrl_dout_vld;
wire  [63:0]     uart_dout;
wire             uart_dout_vld;

top_uart_cfg u_top_uart_cfg(
    .clk        (clk            ),
    .rst_n      (rst_n          ),
    .rx         (rx             ),
    .cfg_head   (16'h55d5       ),
    .din        (cfgCtrl_dout   ),
    .din_vld    (cfgCtrl_dout_vld),
    .dout       (uart_dout      ),
    .dout_vld   (uart_dout_vld  ),
    .tx         (tx             )
);

cfgctrl u_cfgctrl(
    `include "../src/cfgctrl/uart_ledseg_inst.v"
    .clk         (clk           ),
    .rst_n       (rst_n         ),
    .din         (uart_dout     ),
    .din_vld     (uart_dout_vld ),
    .dout        (cfgCtrl_dout  ),
    .dout_vld    (cfgCtrl_dout_vld)
);



ledctrl u_ledctrl(
    .clk        (clk    ),
    .rst_n      (rst_n  ),
    .led_in     (LED_CTRL_data),
    .led_out    (led    )
);

segdisp#(.SEG_NUM(8)) u_segdisp(
    .clk        (clk    ),
    .rst_n      (rst_n  ),
    .din        ({SEG_CTRL1_d7,SEG_CTRL1_d6,
                  SEG_CTRL1_d5,SEG_CTRL1_d4,
                  SEG_CTRL1_d3,SEG_CTRL1_d2,
                  SEG_CTRL1_d1,SEG_CTRL1_d0}    ),
    .din_vld    (8'hff  ),
    .disp_en    (SEG_CTRL0_en),
    .seg_sel    (seg_sel),
    .segment    (segment)
);  

endmodule

 uart顶层文件:

module top_uart_cfg(
    clk     ,
    rst_n   ,
    rx      ,
    cfg_head,
    din     ,
    din_vld ,
    dout    ,
    dout_vld,
    tx      
);

parameter   BPS     = 5208  ;

input           clk         ; 
input           rst_n       ;
input           rx          ;
input [15:0]    cfg_head    ;
input [63:0]    din         ;
input           din_vld     ;
output[63:0]    dout        ;
output          dout_vld    ;
output          tx          ;

wire  [7:0]         uart_rx_out     ;
wire                uart_rx_out_vld ;
wire  [7:0]         uart_tx_in      ;
wire                uart_tx_in_vld  ;
wire                uart_tx_rdy     ;
wire                uart_cfg_p2s_din_rdy;

uart_rx#(.BPS(BPS))  uart_rx(
                 .clk     (clk              ),
                 .rst_n   (rst_n            ),
                 .din     (rx               ),
                 .dout    (uart_rx_out      ),
                 .dout_vld(uart_rx_out_vld  )
             );

uart_cfg_s2p uart_cfg_s2p(
                .clk        (clk            ),
                .rst_n      (rst_n          ),
                .cfg_head   (cfg_head       ),
                .din        (uart_rx_out    ),
                .din_vld    (uart_rx_out_vld),
                .dout       (dout           ),
                .dout_vld   (dout_vld       )

);


uart_cfg_p2s uart_cfg_p2s(
                .clk        (clk            ),
                .rst_n      (rst_n          ),
                .din        (din            ),
                .din_vld    (din_vld        ),
                .dout_rdy   (uart_tx_rdy    ), 
                .dout       (uart_tx_in     ),
                .dout_vld   (uart_tx_in_vld ),
                .din_rdy    (uart_cfg_p2s_din_rdy)
);

uart_tx#(.BPS(BPS))  uart_tx(
                 .clk     (clk              ),
                 .rst_n   (rst_n            ),
                 .din     (uart_tx_in       ),
                 .din_vld (uart_tx_in_vld   ),
                 .rdy     (uart_tx_rdy      ),
                 .dout    (tx               )
             );



endmodule

 uart并串转换:

module uart_cfg_p2s(
    clk        ,
    rst_n      ,
    din        ,
    din_vld    ,
    din_rdy    , 
    dout       ,
    dout_vld   ,
    dout_rdy    
);

parameter           DIN_W  = 64;
parameter           DOUT_W = 8  ;
parameter           C_NUM  = 8  ;

input               clk         ;
input               rst_n       ;
input [ DIN_W-1:0]  din         ;
input               din_vld     ;
output              din_rdy     ;
output[DOUT_W-1:0]  dout        ;
output              dout_vld    ;
input               dout_rdy    ;

wire                flag_add_start;
reg                 flag_add    ;
reg   [ DIN_W-1:0]  din_ff      ;
reg   [ 3:0]        cnt0        ;
wire                add_cnt0    ;
wire                end_cnt0    ;
reg   [DOUT_W-1:0]  dout        ;
reg                 dout_vld    ;
reg                 din_rdy     ;

//reg
assign flag_add_start = flag_add == 0 && din_vld;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_add <= 0;
    end
    else if(flag_add_start) begin
        flag_add <= 1;
    end
    else if(end_cnt0) begin
        flag_add <= 0;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        din_ff <= 0;
    end
    else if(flag_add_start) begin
        din_ff <= din;
    end
end


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        cnt0 <= 0; 
    end
    else if(add_cnt0) begin
        if(end_cnt0)
            cnt0 <= 0; 
        else
            cnt0 <= cnt0+1 ;
   end
end
assign add_cnt0 = (flag_add && dout_rdy);
assign end_cnt0 = add_cnt0  && cnt0 == (C_NUM)-1 ;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout <= 0;
    end
    else if(add_cnt0) begin
        dout <= din_ff[DIN_W-1-cnt0*DOUT_W-:8];
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout_vld <= 0;
    end
    else begin
        dout_vld <= add_cnt0;
    end
end

always  @(*)begin
    if(flag_add || din_vld)
        din_rdy = 0;
    else
        din_rdy = 1;        //褰撴澶勭悊鏁版嵁鏃讹紝鍓嶇涓嶈鍙戞暟鎹繃鏉ワ紱

end

endmodule

 uart串并转换: 

module uart_cfg_s2p(
    clk        ,
    rst_n      ,
    cfg_head   ,
    din        ,
    din_vld    ,
    dout       ,
    dout_vld   

);


input               clk        ;              
input               rst_n      ; 
input [ 15:0]       cfg_head   ;
input [  7:0]       din        ;      
input               din_vld    ;      
output[ 63:0]       dout       ;      
output              dout_vld   ;   

wire                flag_head_start;
reg                 flag_head  ;
reg   [  7:0]       din_ff     ;
reg   [  3:0]       cnt0       ;
wire                add_cnt0   ;
wire                end_cnt0   ;
reg   [ 63:0]       dout       ;
reg                 dout_vld   ;


assign flag_head_start = flag_head==0 && (din_ff == cfg_head[15:8] && din == cfg_head[7:0]) && din_vld;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_head <= 0;
    end
    else if(flag_head_start)begin
        flag_head <= 1;
    end
    else if(end_cnt0)begin
        flag_head <= 0;        
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        din_ff <= 0;
    end
    else if(flag_head==0 && din_vld)begin
        din_ff <= din;
    end
    else if(flag_head)begin
        din_ff <= 0;
    end
end



always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        cnt0 <= 0; 
    end
    else if(add_cnt0) begin
        if(end_cnt0)
            cnt0 <= 0; 
        else
            cnt0 <= cnt0+1 ;
   end
end
assign add_cnt0 = (flag_head && din_vld);
assign end_cnt0 = add_cnt0  && cnt0 == (6)-1 ;


always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout <= 0;
    end
    else if(add_cnt0)begin
        dout[63:48]          <= cfg_head;
        dout[(47)-cnt0*8-:8] <= din;
    end

end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout_vld <= 0;
    end
    else begin
        dout_vld <= end_cnt0;
    end
end


endmodule

 译码

module cfgctrl(
    clk         ,
    rst_n       ,
    din         ,
    din_vld     ,
    `include "../src/cfgctrl/uart_ledseg_intf.v"
    dout        ,
    dout_vld    
    );

parameter           D_W = 64        ;

input               clk             ;
input               rst_n           ;
input[D_W-1:0]      din             ;
input               din_vld         ;
output[D_W-1:0]     dout            ;
output              dout_vld        ;
`include            "../src/cfgctrl/uart_ledseg_io.v"

reg[D_W-1:0]        dout            ;
reg                 dout_vld        ;
wire                reg_wr          ;
wire                reg_rd          ;
wire[14:0]          flag_get_addr   ;
wire[31:0]          flag_get_data   ;

`include "../src/cfgctrl/uart_ledseg_always.v"

assign reg_wr        = din[47]==0 && din_vld;
assign reg_rd        = din[47]==1 && din_vld;
assign flag_get_addr = din[46:32];
assign flag_get_data = din[31:0] ;

always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            dout <= 0;
        end
        else if(din_vld)begin
            dout <= {din[63:32],rdata};
        end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout_vld <= 0;
    end
    else begin
        dout_vld <= reg_rd;
    end
end



endmodule

 其他uart_rx、uart_tx、led驱动、数码管驱动,译码器生成代码 省略说明。

若维护改变代码,仅变动驱动部分代码,及译码生成文件即可,uart和译码部分电路不需要改动。以下链接为全部代码:

上传明细-CSDN创作中心

最后

以上就是感动哈密瓜为你收集整理的实现上位机与FPGA uart交互的全部内容,希望文章能够帮你解决实现上位机与FPGA uart交互所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部