打印
[FPGA]

如何编写约束文件?

[复制链接]
4094|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sxtz531|  楼主 | 2013-10-22 22:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
rxd.rar (2.18 KB)
      这是我写的串口接收部分的代码。在工程中,实例化5个串口,如果用XST综合,其中4个串口可以正常的工作,但有一个串口,发送部分没有问题,在接收中,运行一段时间后,就再也收不到数,作了一些实验可以判断该原因出在,接收的状态机中,一直处于IDLE中中,判断不到起始位,无法向下运行。
     如果用synplify综合,5个串口均可以正常工作,不存在上述问题。
     显然是两种综合工具综合出的电路存在差异。现在想问问诸位,针对这个代码,在XST下,应该如何编写约束,使其综合出来的电路可以正常工作。

相关帖子

沙发
muhan9| | 2013-10-23 08:52 | 只看该作者
我觉得主要问题不应该在约束里面找,如果只是5个串口的程序的话,一个全局时钟约束加管脚约束应该就行了,建议你检查下代码,是不是代码风格的问题

使用特权

评论回复
板凳
sxtz531|  楼主 | 2013-10-23 09:12 | 只看该作者
本帖最后由 sxtz531 于 2013-10-23 09:13 编辑
muhan9 发表于 2013-10-23 08:52
我觉得主要问题不应该在约束里面找,如果只是5个串口的程序的话,一个全局时钟约束加管脚约束应该就行了, ...


        串口只是其中的一部分,整个工程还包括3个SPI的master,4个IIC的slave,一个简单的中断控制,还有10个对外部脉冲计数的16位计数器,以及一些数据同步的逻辑,用于和一个跨时钟域的处理器进行通信。整个资源差不多快80%

使用特权

评论回复
地板
ococ| | 2013-10-23 11:13 | 只看该作者
感觉你的工程时钟速率应该不高。之所以有综合结果的差异很有可能是代码描述产生的。

使用特权

评论回复
5
sxtz531|  楼主 | 2013-10-23 14:25 | 只看该作者
ococ 发表于 2013-10-23 11:13
感觉你的工程时钟速率应该不高。之所以有综合结果的差异很有可能是代码描述产生的。 ...

工作频率不高,只有20MHz。下面是压缩包里的串口接收部分的代码:
//功能:串口接收模块
module rxd(
           clk_i,                  //时钟
           resetn_i,               //复位
           rx_data_i,              //接收的串行数据
           baud_tick_i,            //8倍波特率信号,1个时钟周期高电平的脉冲
           parity_en_i,            //校验位使能
           parity_type_i,          //校验位类型选择
           frame_bits_i,           //接收帧长度
           stop_bits_i,            //停止位长度
           read_status_i,          //读取工作状态
           data_o,                 //接收到数据
           parity_err_o,           //校验错误
           overframe_err_o,        //帧错误  
           rx_rdy_o                //接收准备好信号
          );
          //输入信号
          input         clk_i;
          input         resetn_i;
          input         rx_data_i;
          input         baud_tick_i;
          input         parity_en_i;        //1'b1:使能校验;1'b0:禁止校验
          input         parity_type_i;      //1'b1:奇校验;1'b0:偶校验
          input         stop_bits_i;        //1'b1:2bit停止位;1'b0:1bit停止位
          input[1:0]    frame_bits_i;       //2'b00:5bit;2'b01:6bit;2'b10:7bit;2'b11:8bit
          input         read_status_i;
          //输出信号
          output[7:0]   data_o;
          output        parity_err_o;
          output        overframe_err_o;     
          output        rx_rdy_o;   
          reg[7:0]      data_o;
          reg           parity_err_o;
          reg           overframe_err_o;  //1'b1:帧错误,1'b0:帧正常
          reg           rx_rdy_o;         //1'b1:数据有效可读,1'b0:正在接收数据
         
          parameter  
              IDLE            = 5'h0,
              RX_START        = 5'h1,
              RX_BIT0_WAITE   = 5'h2,
              RX_BIT0         = 5'h3,
              RX_BIT1_WAITE   = 5'h4,
              RX_BIT1         = 5'h5,
              RX_BIT2_WAITE   = 5'h6,
              RX_BIT2         = 5'h7,
              RX_BIT3_WAITE   = 5'h8,
              RX_BIT3         = 5'h9,
              RX_BIT4_WAITE   = 5'ha,
              RX_BIT4         = 5'hb,
              RX_BIT5_WAITE   = 5'hc,
              RX_BIT5         = 5'hd,
              RX_BIT6_WAITE   = 5'he,
              RX_BIT6         = 5'hf,
              RX_BIT7_WAITE   = 5'h10,
              RX_BIT7         = 5'h11,
              RX_PARITY_WAITE = 5'h12,
              RX_PARITY       = 5'h13,
              RX_STOP1_WAITE  = 5'h14,
              RX_STOP1        = 5'h15,
              RX_STOP2_WAITE  = 5'h16,
              RX_STOP2        = 5'h17,
              RX_OVF          = 5'h18;   
          //定义内部信号
          reg[1:0]      divisor_cnt;      //波特率分频
          reg           clr_divisor_cnt;  //
          reg           rx_baud_tick;     //2倍波特率信号
          reg[4:0]      rx_state;  
          reg[7:0]      data_rxd;   
          reg           parity_value;
          reg           overframe;        //帧错误标志,1'b1:帧错误,1'b0:帧正常
          reg           rx_data_rdy;      //数据有效标志,1'b1:数据有效可读,1'b0:正在接收数据
          reg           rx_data_rdy_d1;
                            reg           overframe_d1;
                            reg           parity_value_d1;
                            reg           parity_value_d2;
          /**********************************************
                          分频计数器
                生成2倍波特率脉冲,一个时钟周期宽度
          ***********************************************/
          always @(posedge clk_i or negedge resetn_i)
          begin
                   if(!resetn_i)
                   begin
                             divisor_cnt <= 2'h0;
                             rx_baud_tick <= 1'b0;
                   end
                   else if(clr_divisor_cnt)
                   begin
                             divisor_cnt <= 2'h0;
                   end
                   else if((baud_tick_i == 1'b1) && (rx_state != IDLE))
                   begin
                             if(divisor_cnt == 2'h3)
                             begin
                                      divisor_cnt <= 2'h0;
                                      rx_baud_tick <= 1'b1;
                             end
                             else
                             begin
                                divisor_cnt <= divisor_cnt + 1'b1;
                             end
                   end
                   else
                   begin
                              rx_baud_tick <= 1'b0;
                   end
          end

使用特权

评论回复
6
sxtz531|  楼主 | 2013-10-23 14:25 | 只看该作者
/*********************************************
                         接收状态机
          **********************************************/
          always @(posedge clk_i or negedge resetn_i)
          begin
                    if(!resetn_i)
                    begin
                             rx_state        <= IDLE;
                             clr_divisor_cnt <= 1'b0;
                 overframe       <= 1'b0;
                 data_rxd        <= 8'h0;
                 parity_value    <= 1'b0;
                 rx_data_rdy     <= 1'b0;
                    end
                    else
                    begin
                       clr_divisor_cnt  <= 1'b0;
                             case(rx_state)
                             IDLE:
                             begin
                                       parity_value <= 1'b0;
                                       overframe    <= 1'b0;
                                       rx_data_rdy  <= 1'b0;
                                       if(baud_tick_i == 1'b1)
                                       begin
                                                if(rx_data_i == 1'b0)
                                                begin
                                                          clr_divisor_cnt <= 1'b1;
                                                          rx_state        <= RX_START;
                                                end
                                                else
                                                begin
                                                          clr_divisor_cnt <= 1'b0;
                                                   rx_state        <= IDLE;
                                                end
                                       end
                                       else
                                       begin
                                                clr_divisor_cnt <= 1'b0;
                                                rx_state        <= IDLE;
                                       end
                             end
                             RX_START:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                if(rx_data_i == 1'b1)
                                                begin
                                                          rx_state <= RX_OVF;
                                                end
                                                else
                                                begin
                                                          rx_state <= RX_BIT0_WAITE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state <= RX_START;
                                       end
                             end
                             RX_BIT0_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT0;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT0_WAITE;
                                       end
                             end                             
                             RX_BIT0:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[0]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                rx_state     <= RX_BIT1_WAITE;
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT0;
                                       end
                             end
                 RX_BIT1_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT1;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT1_WAITE;
                                       end
                             end
                             RX_BIT1:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[1]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                rx_state     <= RX_BIT2_WAITE;
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT1;
                                       end
                             end
                             RX_BIT2_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT2;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT2_WAITE;
                                       end
                             end
                             RX_BIT2:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[2]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                rx_state     <= RX_BIT3_WAITE;
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT2;
                                       end
                             end
                             RX_BIT3_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT3;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT3_WAITE;
                                       end
                             end                             
                             RX_BIT3:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[3]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                rx_state     <= RX_BIT4_WAITE;
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT3;
                                       end
                             end
                             RX_BIT4_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT4;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT4_WAITE;
                                       end
                             end
                             RX_BIT4:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[4]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                if((frame_bits_i == 2'b00) && (parity_en_i == 1'b0))  //5bit, 无效验位
                                                begin
                                                          rx_state <= RX_STOP1_WAITE;
                                                end
                                                else if((frame_bits_i == 2'b00) && (parity_en_i == 1'b1)) //5bit,有效验位
                                                begin
                                                          rx_state <= RX_PARITY_WAITE;
                                                end
                                                else
                                                begin
                                                          rx_state <= RX_BIT5_WAITE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT4;
                                       end
                             end
                             RX_BIT5_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT5;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT5_WAITE;
                                       end
                             end
                             RX_BIT5:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[5]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                if((frame_bits_i == 2'b01) && (parity_en_i == 1'b0))  //6bit, 无效验位  
                                                begin
                                                          rx_state <= RX_STOP1_WAITE;
                                                end
                                                else if((frame_bits_i == 2'b01) && (parity_en_i == 1'b1))//6bit,有效验位  
                                                begin
                                                          rx_state <= RX_PARITY_WAITE;
                                                end
                                                else
                                                begin
                                                          rx_state <= RX_BIT6_WAITE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT5;
                                       end
                             end
                 RX_BIT6_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT6;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_BIT6_WAITE;
                                       end
                             end
                             RX_BIT6:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[6]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                if((frame_bits_i == 2'b10) && (parity_en_i == 1'b0))  //7bit, 无效验位  
                                                begin
                                                          rx_state <= RX_STOP1_WAITE;
                                                end
                                                else if((frame_bits_i == 2'b10) && (parity_en_i == 1'b1))//7bit,有效验位  
                                                begin
                                                          rx_state <= RX_PARITY_WAITE;
                                                end
                                                else
                                                begin
                                                          rx_state <= RX_BIT7_WAITE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT6;
                                       end
                             end
                             RX_BIT7_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_BIT7;
                                       end
                                       else
                                       begin
                                                 rx_state <= RX_BIT7_WAITE;
                                       end
                             end
                             RX_BIT7:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                data_rxd[7]  <= rx_data_i;
                                                parity_value <= parity_value ^ rx_data_i;
                                                rx_state     <= RX_BIT7_WAITE;
                                                if(parity_en_i == 1'b1)    //8bit, 有效验位  
                                                begin
                                                          rx_state <= RX_PARITY_WAITE;
                                                end
                                                else                       //8bit, 无效验位  
                                                begin
                                                          rx_state <= RX_STOP1_WAITE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state    <= RX_BIT7;
                                       end
                             end      
                             RX_PARITY_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_PARITY;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_PARITY_WAITE;
                                       end
                             end                       
                             RX_PARITY:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                if(parity_type_i == 1'b1)     //奇校验
                                                begin
                                                          parity_value <= ((~parity_value) != rx_data_i);   
                                                end
                                                else                          //偶校验
                                                begin
                                                          parity_value <= (parity_value != rx_data_i);
                                                end
                                                rx_state <= RX_STOP1_WAITE;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_PARITY;
                                       end
                             end
                             RX_STOP1_WAITE:
                             begin
                                       rx_data_rdy <= 1'b1;
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                        rx_state <= RX_STOP1;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_STOP1_WAITE;
                                       end
                             end
                             RX_STOP1:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                if(stop_bits_i == 1'b1)
                                                begin
                                                          rx_state <= RX_STOP2_WAITE;
                                                end
                                                else
                                                begin
                                                          rx_state <= IDLE;
                                                end
                                       end
                                       else
                                       begin
                                                rx_state <= RX_STOP1;
                                       end
                             end
                             RX_STOP2_WAITE:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= RX_STOP2;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_STOP2_WAITE;
                                       end
                             end
                             RX_STOP2:
                             begin
                                       if(rx_baud_tick == 1'b1)
                                       begin
                                                rx_state <= IDLE;
                                       end
                                       else
                                       begin
                                                rx_state <= RX_STOP2;
                                       end
                             end
                             RX_OVF:
                             begin
                                       overframe <= 1'b1;
                                       rx_state  <= IDLE;
                             end
                             default:
                             begin
                                       rx_state <= IDLE;
                             end
                             endcase
                    end
          end
         
          /****************************************************
              读取工作状态后,清除帧、校验错误、空满标志位
          ****************************************************/
          always @(posedge clk_i or negedge resetn_i)
          begin
                   if(!resetn_i)
                   begin
                             parity_err_o    <= 1'b0;
                             overframe_err_o <= 1'b0;
                             rx_rdy_o        <= 1'b0;
                   end
                   else if(read_status_i)
                   begin
                             parity_err_o    <= 1'b0;
                             overframe_err_o <= 1'b0;
                             rx_rdy_o        <= 1'b0;
                   end
                   else
                   begin
                             parity_err_o    <= parity_err_o    | ((!parity_value_d2) && (parity_value_d1));
                             overframe_err_o <= overframe_err_o | ((!overframe_d1) && (overframe));
                             rx_rdy_o        <= rx_rdy_o        | ((!rx_data_rdy_d1) && (rx_data_rdy));
                   end
          end
         
          /******************************************
                    送出接收到的数据
          *******************************************/
          always @(posedge clk_i or negedge resetn_i)
          begin
                   if(!resetn_i)
                   begin
                             data_o <= 8'h0;
                   end
                   else if(rx_data_rdy)
                   begin
                             case(frame_bits_i)
                             2'b00:
                             begin
                                      data_o <= {3'b0,data_rxd[4:0]};
                             end
                             2'b01:
                             begin
                                      data_o <= {2'b0,data_rxd[5:0]};
                             end
                             2'b10:
                             begin
                                      data_o <= {1'b0,data_rxd[6:0]};
                             end
                             2'b11:
                             begin
                                      data_o <= data_rxd;
                             end
                             endcase
                   end
          end
         
          /*****************************************
                    延时,用于边沿检测
          ******************************************/
          always @(posedge clk_i or negedge resetn_i)
          begin
                   if(!resetn_i)
                   begin
                             rx_data_rdy_d1 <= 1'b0;
                                              overframe_d1   <= 1'b0;
                   end
                   else
                   begin
                             rx_data_rdy_d1 <= rx_data_rdy;
                                              overframe_d1   <= overframe;
                   end
          end
                         
                         always @(posedge clk_i or negedge resetn_i)
                         begin
                            if(!resetn_i)
                                  begin
                                    parity_value_d1 <= 1'b0;
                                          parity_value_d2 <= 1'b0;
                                 end
                                 else if(rx_state == RX_STOP1_WAITE)
                                 begin
                                    parity_value_d1 <= parity_value;
                                          parity_value_d2 <= parity_value_d1;
                                 end
                                 else
                                 begin
                                    parity_value_d1 <= 1'b0;
                                          parity_value_d2 <= 1'b0;
                                 end
                         end
endmodule

使用特权

评论回复
7
sxtz531|  楼主 | 2013-10-23 14:26 | 只看该作者
这样写代码有什么地方存在不足之处,请指教,谢谢。

使用特权

评论回复
8
gon_wen| | 2013-10-23 14:29 | 只看该作者
约束,,只可以告诉你一个大概的过程,,用create_clock定义时钟,如果有生成的时钟加generate_clock命令来定义,有多个时钟加个set_false_path以免做STA时报错,这些都是DC的命令,到FPGA可能不适用,不过原理是一样的,,如果你的设计不复杂,这就够用了,,后面就是看你的STA了,,看看report有没有错,,,,用ISE综合,把约束加到UCF文件,,用synplify综合约束加到SDC文件。。其实做FPGA设计不需要加很多约束的,基本上定义了时钟就差不多了,,。。。。

对于你这个问题,,建议你把rx_data_i这个信号用clk_i时钟做一下同步处理。

使用特权

评论回复
9
sxtz531|  楼主 | 2013-10-23 21:31 | 只看该作者
gon_wen 发表于 2013-10-23 14:29
约束,,只可以告诉你一个大概的过程,,用create_clock定义时钟,如果有生成的时钟加generate_clock命令来 ...

谢谢你的指点。不过还有些疑惑,就是rx_data_i与clk_i的变化频率不在一个数量级上,意思也就是,rx_data_i应该可以认为是稳定的输入吧,这样也不用在考虑同步处理的问题吧。

使用特权

评论回复
10
gon_wen| | 2013-10-24 11:45 | 只看该作者
rx_data_i与clk_i的变化频率不在一个数量级上,意思也就是,rx_data_i应该可以认为是稳定的输入吧,这样也不用在考虑同步处理的问题吧,,。。。关于这个问题,你就大错特别错了,只要是异步的信号,都要经过同步处理,除非你的电路设计时就采用其它方式特别处理过,确保不会出现时序上的问题。。。
如果rx_data_i没有经过clk_i同步,,结果就是稳定性差,。。数据的变化率低只是出错的概率小些而已,,。。你的设计中clk_i和rx_data_i的频率都比较低,个人感觉运行个几个小时应该还是不会出问题的,,所以你可以看看是不是你的UART以外的代码设计有问题,,
祝你早日解决,:lol

使用特权

评论回复
11
GoldSunMonkey| | 2013-10-24 23:11 | 只看该作者
希望大家多讨论啊

使用特权

评论回复
12
sxtz531|  楼主 | 2013-10-24 23:30 | 只看该作者
gon_wen 发表于 2013-10-24 11:45
rx_data_i与clk_i的变化频率不在一个数量级上,意思也就是,rx_data_i应该可以认为是稳定的输入吧,这样也 ...

谢谢,希望有足够好的运气。

使用特权

评论回复
13
sxtz531|  楼主 | 2013-10-24 23:32 | 只看该作者
GoldSunMonkey 发表于 2013-10-24 23:11
希望大家多讨论啊

猴哥有什么可以指点的呀

使用特权

评论回复
14
Backkom80| | 2013-10-25 10:16 | 只看该作者
约束分:
1,IO约束,IO的位置,电气特性等
2,时序约束,这个和你设计要求有关
3,位置,如将某个bram,或dsp,或LUT放在某个位置

使用特权

评论回复
15
GoldSunMonkey| | 2013-10-25 23:14 | 只看该作者
sxtz531 发表于 2013-10-24 23:32
猴哥有什么可以指点的呀

看下面贝壳的回答

使用特权

评论回复
16
GoldSunMonkey| | 2013-10-25 23:14 | 只看该作者
sxtz531 发表于 2013-10-24 23:32
猴哥有什么可以指点的呀

贝壳忙什么呢?

使用特权

评论回复
17
beanandpeach| | 2016-1-13 15:08 | 只看该作者

使用特权

评论回复
18
cnb12345| | 2016-1-13 23:56 | 只看该作者
看看,帮不上

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

37

帖子

0

粉丝