OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7012|回复: 0

[ALTERA] 使用双口ram进行uart通信,串口调试助手只显示输入的最后一位数据的一半

[复制链接]

2

主题

3

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2020-5-19
在线时间
5 小时
发表于 2020-6-2 15:15:56 | 显示全部楼层 |阅读模式
1金钱


下面是控制模块代码:
目的是按键按下可以进行读数据
module ctrl(
                input           key,
                input           clk,
                input           rst_n,
                input           rxd_done,
                input           txd_done,
                output          wr_en,
                output  reg[7:0]wraddr,
                output  reg[7:0]rdaddr,
                output  reg     txd_en
            );

wire        key_flag,key_value;
reg         key_reg0,key_reg1;
wire        key_edge;       //检测按键下降沿
reg         reg_txd_done;


key_debounce  key_u1(
        .clk(clk),
        .rst_n(rst_n),
        .key(key),
        .key_flag(key_flag),   
        .key_value(key_value)
        );     
/*     
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        key_reg0    <= 1'b0;
        key_reg1    <= 1'b0;
    end
    else begin
        key_reg0    <= key_value;
        key_reg1    <= key_reg0;
    end
end

assign  key_edge  =  (~key_reg0) & key_reg1;
*/
assign  wr_en = rxd_done;       // 接收端数据和完成信号是同步的,没有延迟时钟周期,直接写第一个数据地址为零?
//根据接收端完成信息后进行赋值写地址
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        wraddr  <= 8'd0;
    end
    else if(rxd_done)
        wraddr  <= wraddr + 1'b1;
    else
        wraddr  <= wraddr;
end


always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        reg_txd_done    <= 1'b0;
     else
        reg_txd_done    <= key_flag & (~key_value);
end
/*
always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        rdaddr      <= 8'd0;
     else if((key_flag & (~key_value))& txd_done)
        rdaddr      <= rdaddr + 1'b1;
     else
        rdaddr      <= rdaddr;

end
*/
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        txd_en      <= 1'b0;
    end
    else if( key_flag & (~key_value))
    txd_en      <= 1'b1;        //txd_done完成的时间和数据发送完同步不需要延迟一个周期赋值txd_en?
  //  else if (reg_txd_done)
  //  txd_en      <= 1'b1;
    else
        txd_en      <= 1'b0;
end

endmodule

   //发送模块
  module uart_send(
                input       txd_en,
                input       clk,
                input       rst,
                input [7:0] uart_din,
                output reg  txd_data,
                output reg  txd_done
                );

parameter    clk_freq = 50_000_000;
parameter    uart_bps = 9600;
localparam   bps_cnt = clk_freq/uart_bps ;      //传输一个bit数据要求的计数值

reg     txd_reg0,txd_reg1;
wire    start_flag;           //上升沿标志

reg  [3:0]   data_cnt;      //传输一帧数据计数
reg  [15:0]  bit_cnt;       //传输1个bit时间计数

reg          txd_flag;

reg  [7:0]   uart_data;
always@(posedge clk or negedge rst ) begin
       if(!rst) begin
            txd_reg0    <= 1'b0;
            txd_reg1    <= 1'b0;
       end
       else begin
            txd_reg0    <= txd_en;
            txd_reg1    <= txd_reg0;
       end
end

assign  start_flag  = txd_reg0 & (~txd_reg1);

//计算传输的数据位
always@(posedge clk or negedge rst) begin
        if(!rst) begin
            data_cnt    <= 4'd0;
            bit_cnt     <= 16'd0;
        end
        else if(txd_flag) begin
                if(bit_cnt < bps_cnt - 1'b1) begin
                    data_cnt    <=  data_cnt;
                    bit_cnt     <=  bit_cnt + 1'b1;
                end
                else begin
                    data_cnt    <=  data_cnt + 1'b1;
                    bit_cnt     <=  16'd0;
                end
        end
        else begin
            data_cnt    <= 4'd0;
            bit_cnt     <= 16'd0;
             end
end
//计算flag数据结束位
always@(posedge clk or negedge rst) begin
        if(!rst) begin
            txd_flag    <= 1'b0;
            uart_data   <= 8'd0;
        end
        else begin
           if(start_flag) begin
            txd_flag    <= 1'b1;
            uart_data   <= uart_din;
            end
           else if((data_cnt == 4'd9)&& (bit_cnt == bps_cnt/2)) begin    //检测最后一个数据中间位置,因为传输数据是连续的下一位为数据起始位
            txd_flag    <= 1'b0;
            uart_data   <= 8'd0;
            end
           else begin
            txd_flag    <= txd_flag;
            uart_data   <= uart_data;
            end
        end
end
//并串转换
always@(posedge clk or negedge rst) begin
        if(!rst) begin
            txd_data   <= 1'd1;
          //  txd_done   <= 1'b0;
        end
        else if(txd_flag) begin
            case(data_cnt)
            4'd0 : txd_data    <= 1'b0;
            4'd1 : txd_data    <= uart_data[0];
            4'd2 : txd_data    <= uart_data[1];
            4'd3 : txd_data    <= uart_data[2];
            4'd4 : txd_data    <= uart_data[3];
            4'd5 : txd_data    <= uart_data[4];
            4'd6 : txd_data    <= uart_data[5];
            4'd7 : txd_data    <= uart_data[6];
            4'd8 : txd_data    <= uart_data[7];
            4'd9 : txd_data    <= 1'b1;            //停止位
            default : ;           
            endcase
        end
        else begin
            txd_data    <= 1'b1;     
           // txd_done    <= 1'b0;
        end
end

always@(posedge clk or negedge rst) begin
        if(!rst) begin
            txd_done    <= 1'b0;
        end
        else if(data_cnt == 4'd9) begin
            txd_done    <= 1'b1;
        end
        else begin
            txd_done    <= 1'b0;
             end
end
endmodule











































































正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-27 08:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表