sasinop 发表于 2013-5-25 10:19:53

串口分支 程序 如何 整合到一起?

功能需求
PC发送数据包格式如下:
bootcode len cmd para checksum

比如发送
40 03 02 01 BB
该命令包的命令码就是:02 ,参数:01
当FPGA 收到命名包,并解析命令包,
当命令码为:02时 , 且参数为:01;调用 音乐播放模块,并播放音乐..

再发送: 40 03 02 02 BA 是
当FPGA 收到命名包,并解析命令包,
当命令码为:02时 , 且参数为:02;停止播放音乐..

请问如何在这个基础上修改呢? 谢谢module my_uart_top(clk,rst_n,rs232_rx,rs232_tx);

input clk; // 主时钟
input rst_n;//低电平复位信号
input rs232_rx;   // RS232接收数据信号
output rs232_tx;//RS232发送数据信号

wire bps_start1,bps_start2;   //接收到数据后,波特率时钟启动信号置位
wire clk_bps1,clk_bps2;   // clk_bps的高电平为接收或者发送数据位的中间采样点
wire rx_data;   //接收数据寄存器,保存直至下一个数据来到
wire rx_int;//接收数据中断信号,接收到数据期间始终为高电平
//----------------------------------------------------
speed_select      speed_rx( .clk(clk), //波特率选择模块,接收和发送模块复用,不支持全双工通信
                                        .rst_n(rst_n),
                                        .bps_start(bps_start1),
                                        .clk_bps(clk_bps1)
                                        );

my_uart_rx      my_uart_rx(       .clk(clk), //接收数据模块
                                        .rst_n(rst_n),
                                        .rs232_rx(rs232_rx),
                                        .clk_bps(clk_bps1),
                                        .bps_start(bps_start1),
                                        .rx_data(rx_data),
                                        .rx_int(rx_int)
                                        );
            
speed_select      speed_tx( .clk(clk), //波特率选择模块,接收和发送模块复用,不支持全双工通信
                                        .rst_n(rst_n),
                                        .bps_start(bps_start2),
                                        .clk_bps(clk_bps2)
                                        );
my_uart_tx      my_uart_tx(       .clk(clk), //发送数据模块
                                        .rst_n(rst_n),
                                        .clk_bps(clk_bps2),
                                        .rx_data(rx_data),
                                        .rx_int(rx_int),
                                        .rs232_tx(rs232_tx),
                                        .bps_start(bps_start2)
                                        );

endmodule
module my_uart_rx(clk,rst_n,rs232_rx,clk_bps,bps_start,rx_data,rx_int);

input clk; // 主时钟
input rst_n;//低电平复位信号
input rs232_rx;   // RS232接收数据信号!!
input clk_bps;    // clk_bps的高电平为接收或者发送数据位的中间采样点
output bps_start; //接收到数据后,波特率时钟启动信号置位
output rx_data; //接收数据寄存器,保存直至下一个数据来到
output rx_int;    //接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2; //接收数据寄存器,滤波用
wire neg_rs232_rx;   //表示数据线接收到下降沿

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            rs232_rx0 <= 1'b1;
            rs232_rx1 <= 1'b1;
            rs232_rx2 <= 1'b1;
      end
   else begin
            rs232_rx0 <= rs232_rx;
            rs232_rx1 <= rs232_rx0;
            rs232_rx2 <= rs232_rx1;
      end
end

assign neg_rs232_rx = rs232_rx2 & ~rs232_rx1; //接收到下降沿后neg_rs232_rx置高一个时钟周期??

//----------------------------------------------------------------
reg bps_start_r;
reg   num;   //移位次数
reg rx_int;   //接收数据中断信号,接收到数据期间始终为高电平

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            bps_start_r <= 1'b0;
            rx_int <= 1'b0;
      end
   else if(neg_rs232_rx) begin
            bps_start_r <= 1'b1; //启动接收数据
         rx_int <= 1'b1;   //接收数据中断信号使能
            end
   else if(num==4'd10) begin                      //??
            bps_start_r <= 1'b0; //数据接收完毕
            rx_int <= 1'b0;      //接收数据中断信号关闭
      end
end
assign bps_start = bps_start_r;

//----------------------------------------------------------------
reg rx_data_r;//接收数据寄存器,保存直至下一个数据来到
//----------------------------------------------------------------

reg   rx_temp_data; //当前接收数据寄存器
reg rx_data_shift;   //数据移位标志

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            rx_data_shift <= 1'b0;
            rx_temp_data <= 8'd0;
            num <= 4'd0;
            rx_data_r <= 8'd0;
      end
   else if(rx_int) begin    //接收数据处理
      if(clk_bps) begin //读取并保存数据,接收数据为一个起始位,8bit数据,一个结束位      
            rx_data_shift <= 1'b1;
               num <= num+1'b1;
               if(num<=4'd8) rx_temp_data <= rs232_rx;    //锁存9bit(1bit起始位,8bit数据)   ??如何配置rs232_rx
            end
      else if(rx_data_shift) begin    //数据移位处理   
            rx_data_shift <= 1'b0;
               if(num<=4'd8) rx_temp_data <= rx_temp_data >> 1'b1;//移位8次,第1bit起始位移除,剩下8bit正好是接收数据
               else if(num==4'd10) begin
                      num <= 4'd0;//接收到STOP位后结束,num清零
                      rx_data_r <= rx_temp_data;//把数据锁存到数据寄存器rx_data中
                   end
            end
      end
end

assign rx_data = rx_data_r;
endmodule

module my_uart_tx(clk,rst_n,clk_bps,rx_data,rx_int,rs232_tx,bps_start);

input clk;    // 主时钟
input rst_n;//低电平复位信号
input clk_bps;       // clk_bps的高电平为接收或者发送数据位的中间采样点
input rx_data;//接收数据寄存器
input rx_int;   //接收数据中断信号,接收到数据期间始终为高电平,在次利用它的下降沿来启动发送数据
output rs232_tx;// RS232发送数据信号
output bps_start; //接收或者要发送数据,波特率时钟启动信号置位
//---------------------------------------------------------
reg rx_int0,rx_int1,rx_int2;    //rx_int信号寄存器,捕捉下降沿滤波用
wire neg_rx_int;// rx_int下降沿标志位

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            rx_int0 <= 1'b0;
            rx_int1 <= 1'b0;
            rx_int2 <= 1'b0;
      end
   else begin
            rx_int0 <= rx_int;
            rx_int1 <= rx_int0;
            rx_int2 <= rx_int1;
      end
end

assign neg_rx_int =~rx_int1 & rx_int2;//捕捉到下降沿后,neg_rx_int拉地保持一个主时钟周期??

//---------------------------------------------------------
reg tx_data; //待发送数据的寄存器
//---------------------------------------------------------
reg bps_start_r;
reg tx_en; //发送数据使能信号,高有效
reg num;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            bps_start_r <= 1'b0;
            tx_en <= 1'b0;
            tx_data <= 8'd0;
      end
   else if(neg_rx_int) begin   //接收数据完毕,准备把接收到的数据发回去
            bps_start_r <= 1'b1;
            tx_data <= rx_data;//把接收到的数据存入发送数据寄存器
            tx_en <= 1'b1;       //进入发送数据状态中
      end
   else if(num==4'd10) begin   //数据发送完成,复位
            bps_start_r <= 1'b0;
            tx_en <= 1'b0;
      end
end

assign bps_start = bps_start_r;

//---------------------------------------------------------
reg rs232_tx_r;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
            num <= 4'd0;
            rs232_tx_r <= 1'b1;
      end
   else if(tx_en) begin
            if(clk_bps)   begin
                   num <= num+1'b1;
                   case (num)
                      4'd0:rs232_tx_r <= 1'b0; //发送起始位
                      4'd1:rs232_tx_r <= tx_data;   //发送bit0
                      4'd2:rs232_tx_r <= tx_data;   //发送bit1
                      4'd3: rs232_tx_r <= tx_data; //发送bit2
                      4'd4: rs232_tx_r <= tx_data; //发送bit3
                      4'd5: rs232_tx_r <= tx_data; //发送bit4
                      4'd6: rs232_tx_r <= tx_data; //发送bit5
                      4'd7:rs232_tx_r <= tx_data;   //发送bit6
                      4'd8: rs232_tx_r <= tx_data; //发送bit7
                      4'd9: rs232_tx_r <= 1'b1;   //发送结束位
                     default: rs232_tx_r <= 1'b1;
                      endcase
               end
            else if(num==4'd10) num <= 4'd0;   //复位
      end
end

assign rs232_tx = rs232_tx_r;//如何配置rs232_tx???

endmodule
module speed_select(clk,rst_n,bps_start,clk_bps);

input clk; // 主时钟
input rst_n;//低电平复位信号
input bps_start;//接收到数据后,波特率时钟启动信号置位
output clk_bps;   // clk_bps的高电平为接收或者发送数据位的中间采样点
parameter   bps9600    = 5208,//5207,    //波特率为9600bps 这里使用FPGA主频计算11.06962Mhz,5207是50MHz主频计算值
               bps19200   = 2603,    //波特率为19200bps
               bps38400   = 1301,    //波特率为38400bps
               bps57600   = 867, //波特率为57600bps
               bps115200= 433; //波特率为115200bps

parameter   bps9600_2   = 2604,//2603,
               bps19200_2= 1301,
               bps38400_2= 650,
               bps57600_2= 433,
               bps115200_2 = 216;

reg bps_para;//分频计数最大值,以前是13位数据,但是总是有报警,所以我就给改成了32为数据,没有了多余的报警
reg bps_para_2;    //分频计数的一半
/*`define   bps_para   5207   //因为这个uart_ctrl在always中会产生报警,所以使用伪指令的宏定义
`define   bps_para_2   2603*/   //这个宏定义的参数在使用的时候必须给参数前加一个`例如:`bps_para_2
reg cnt;         //分频计数
reg clk_bps_r;         //波特率时钟寄存器

//----------------------------------------------------------
reg uart_ctrl;// uart波特率选择寄存器,怎样配置uart_ctr??
//----------------------------------------------------------

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) begin
         uart_ctrl <= 3'd0;   //默认波特率为9600bps
      end
   else begin
            case (uart_ctrl)//波特率设置
               3'd0:begin
                      bps_para <= bps9600;
                      bps_para_2 <= bps9600_2;
                      end
               3'd1:begin
                      bps_para <= bps19200;
                      bps_para_2 <= bps19200_2;
                      end
               3'd2:begin
                      bps_para <= bps38400;
                      bps_para_2 <= bps38400_2;
                      end
               3'd3:begin
                      bps_para <= bps57600;
                      bps_para_2 <= bps57600_2;
                      end
               3'd4:begin
                      bps_para <= bps115200;
                      bps_para_2 <= bps115200_2;
                      end
               default: ;
               endcase
      end
end

always @ (posedge clk or negedge rst_n)
   if(!rst_n) cnt <= 13'd0;
   else if(cnt<bps_para && bps_start) cnt <= cnt+1'b1;//波特率时钟计数启动
   else cnt <= 13'd0;

always @ (posedge clk or negedge rst_n)
   if(!rst_n) clk_bps_r <= 1'b0;
   else if(cnt==bps_para_2 && bps_start) clk_bps_r <= 1'b1;    // clk_bps_r高电平为接收或者发送数据位的!中间!采样点
    else clk_bps_r <= 1'b0;

assign clk_bps = clk_bps_r;

endmodule播放音乐的模块如下所示:module top(sp,   
      
      led,
          clk,
      rst_n);

output                sp;

output   led;
input                clk;
input                rst_n; // synthesis attribute clock_buffer of rst_n is ibufg;

reg      clk_cnt;
always @ ( posedge clk or negedge rst_n)
    if (!rst_n )
      clk_cnt <= 24'd0;
    else
      clk_cnt <= clk_cnt + 1'b1;

wireclk_6mhz = (clk_cnt||(clk_cnt&&clk_cnt));                        //(clk_cnt&&clk_cnt);
wireclk_4hz= (clk_cnt&&clk_cnt);
      
wire       high,med,low;      




assign    led = |{high,med,low};
assign    led = |{high,med};
assign    led = |high;
song song_inst
    (
    .clk_6mhz   (clk_6mhz),
    .clk_4hz    (clk_4hz),
    .sp         ( sp    ),
    .high       ( high),
    .med      ( med   ),
    .low      ( low   )
    );



endmodule

深海烟花 发表于 2013-5-25 10:55:34

lz,分模块设计就行.一块一块的功能划分好.

wangjun403 发表于 2013-5-25 13:02:36

一、这个串口程序没有将接受到每个字节的标志位拉出,你要找到关键地方,将这个标志位拉出来
二、你要的功能关键是要实现对数据的按协议解码,因为这都是单向传输,还是比较简单的

sasinop 发表于 2013-5-30 05:57:08

搜搜,没找到差不多的结构的例子参考

都是自收自发的多...
页: [1]
查看完整版本: 串口分支 程序 如何 整合到一起?