发新帖我要提问
12
返回列表
打印

AD采样数据同步问题

[复制链接]
楼主: iampeter
手机看帖
扫描二维码
随时随地手机跟帖
21
可以啊

使用特权

评论回复
22
gaoxuxu123456| | 2012-3-22 18:43 | 只看该作者
ad7864_controller adc_ctrl(
  clock_i,
  reset_ni,
  start_i,
  started_o,  
  over_o,
  data_o,
  cs_no,
  rd_no,
  convst_no,
  busy_i,
  db_i
);
  parameter data_width = 12;
input clock_i;
  input reset_ni;
  input start_i;
  output reg started_o;
  output reg over_o;
  output reg [data_width-1:0] data_o;

  output cs_no;      // CS*
  output reg rd_no;  // RD*
  output reg convst_no; // CONVST*
  input busy_i;
  input [data_width-1:0] db_i;     // DB11 - DB0
reg [4:1] state;
localparam s_idle       = 4'b0001;
localparam s_convst     = 4'b0010; // start conversion
localparam s_wait_busy  = 4'b0100; // wait busy's negative edge
localparam s_get_data   = 4'b1000; // read the converted data

reg busy_former;

`define NEGATIVE_BUSY ((busy_former) && !(busy_i))

assign cs_no = 1'b0;

// state machine
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) state <= s_idle;
  else case(state)
    s_idle: if(start_i) state <= s_convst;
    s_convst: state <= s_wait_busy;
    s_wait_busy: if(`NEGATIVE_BUSY) state <= s_get_data;
    s_get_data: state <= s_idle;
    default: state <= s_idle;
  endcase
end

always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) busy_former <= 1'b0;
  else busy_former <= busy_i;
end

// start conversion
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) convst_no <= 1'b1;
  else case(state)
    s_idle: if(start_i) convst_no <= 1'b0; // Note: clock period > 35ns
    default: convst_no <= 1'b1;
  endcase
end

// read from AD7864
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) rd_no <= 1'b1;
  else case(state)
    s_wait_busy: if(`NEGATIVE_BUSY) rd_no <= 1'b0;// Note: clock period > 35ns
    default: rd_no <= 1'b1;
  endcase
end

// register data comming from AD7864
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) data_o <= {data_width{1'b0}};
  else case(state)
    s_get_data: data_o <= db_i;
  endcase
end

// indicating converion is over and data is read
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) over_o <= 1'b0;
  else case(state)
    s_get_data: over_o <= 1'b1;
    default: over_o <= 1'b0;
  endcase
end

// conversion started, analog signal has alread held,
// waiting for conversion finished
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) started_o <= 1'b0;
  else case(state)
    s_convst: started_o <= 1'b1;
    default: started_o <= 1'b0;
  endcase
end
endmodule


module xuxu (clock_i,
  reset_ni,
  start_i,
  started_o,  
  over_o,
  data_o,
  cs_no,
  rd_no,
  convst_no,
  busy_i,
  db_i
);
parameter data_width = 12;
input clock_i;
input reset_ni;
input start_i;
output reg started_o;
output reg over_o;
output reg [data_width-1:0] data_o;
output cs_no;      // CS*
output reg rd_no;  // RD*
output reg convst_no; // CONVST*
input busy_i;
input [data_width-1:0] db_i;     // DB11 - DB0
reg [4:1] state;

localparam s_idle       = 4'b0001;
localparam s_convst     = 4'b0010; // start conversion
localparam s_wait_busy  = 4'b0100; // wait busy's negative edge
localparam s_get_data   = 4'b1000; // read the converted data

reg busy_former;

`define NEGATIVE_BUSY ((busy_former) && !(busy_i))

assign cs_no = 1'b0;

// state machine
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) state <= s_idle;
  else case(state)
    s_idle: if(start_i) state <= s_convst;
    s_convst: state <= s_wait_busy;
    s_wait_busy: if(`NEGATIVE_BUSY) state <= s_get_data;
    s_get_data: state <= s_idle;
    default: state <= s_idle;
  endcase
end

always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) busy_former <= 1'b0;
  else busy_former <= busy_i;
end

// start conversion
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) convst_no <= 1'b1;
  else case(state)
    s_idle: if(start_i) convst_no <= 1'b0; // Note: clock period > 35ns
    default: convst_no <= 1'b1;
  endcase
end

// read from AD7864
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) rd_no <= 1'b1;
  else case(state)
    s_wait_busy: if(`NEGATIVE_BUSY) rd_no <= 1'b0;// Note: clock period > 35ns
    default: rd_no <= 1'b1;
  endcase
end

// register data comming from AD7864
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) data_o <= {data_width{1'b0}};
  else case(state)
    s_get_data: data_o <= db_i;
  endcase
end

// indicating converion is over and data is read
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) over_o <= 1'b0;
  else case(state)
    s_get_data: over_o <= 1'b1;
    default: over_o <= 1'b0;
  endcase
end

// conversion started, analog signal has alread held,
// waiting for conversion finished
always @(posedge clock_i or negedge reset_ni) begin
  if(!reset_ni) started_o <= 1'b0;
  else case(state)
    s_convst: started_o <= 1'b1;
    default: started_o <= 1'b0;
  endcase
end





Endmodule

module fsm(clock_i,reset_n,busy_i,frstdata,eoc):
input clock_i,reset_n,busy_i,frstdata,eoc;
reg[2:0] state;
parameter idle=3’h0,sua=3’h1,sub=3’h2,suc=3’h3,sud=3’h4;
always@(posedge clock_i or negedge reset_n or state)
     begin
       if(!reset_n)
        state=idle;
       else begin
          case(state)
           idle:begin if(frstdata) state=sua;
                       else  state=idle;
                 end
           sua:begin  if(!eoc)
                     state=sub;
                    else state=sua;
                end
           sub:begin  if(!eoc)
                      state=suc;
                      else state=sub;
                 end
           suc:begin  if(!eoc)
                      state=sud;
                      else state=sud;
               end
           sud:begin  if(busy)
                      state=sud;
                      else state=idle;
               end
           defalt:state=idle;
         endcase

使用特权

评论回复
23
charrijon| | 2012-3-22 19:33 | 只看该作者
好好研究研究时序吧,肯定有办法解决的,这种问题很常见,最终都可以通过时序配合来解决的

使用特权

评论回复
24
iampeter|  楼主 | 2012-3-22 20:21 | 只看该作者
谢谢大家!!!

使用特权

评论回复
25
lwq030736| | 2012-3-22 21:24 | 只看该作者
读AD数据时跟AD用同一个时钟
把数据写到异步FIFO里
FPGA再用自己的时钟从异步FIFO读数据
另外要注意AD的时钟线和数据线要等长,
如果不等就要根据每个数据口实际的延时进行TSU的约束

使用特权

评论回复
26
lwq030736| | 2012-3-22 21:31 | 只看该作者
如果你的图是逻辑分析仪抓出来的
那么可能第11位的走线太长,延时过长了
约束下第11位的TSU看能不能改善
如果实在无法缩短第11位的延时,就增加其他位的延时
可以调整输入口的输入延时,具体操作我只用过QUARTUS的
ISE没用过,你可以找找资料

使用特权

评论回复
27
philoman| | 2012-3-23 22:27 | 只看该作者
LS fen xi hen you dao li

使用特权

评论回复
28
liwsx| | 2012-3-25 11:49 | 只看该作者
路过     ,
像大家学习了          ,
都是高手啊       

使用特权

评论回复
29
vivisa| | 2012-3-25 17:36 | 只看该作者
MARK

使用特权

评论回复
30
abcsmile| | 2012-3-26 11:25 | 只看该作者
不错,哈哈:D

使用特权

评论回复
31
duthongbin| | 2012-3-29 10:07 | 只看该作者
MARK,学习:)

使用特权

评论回复
32
duthongbin| | 2012-3-29 11:47 | 只看该作者
顺便问下LZ,你起初的AD时钟是从FPGA分频出来的,怎么写得代码(最好是VHDL的)?我遇到FPGA的管脚时钟输出不出来的情况,高低电平倒是没有问题。 24# iampeter

使用特权

评论回复
33
iampeter|  楼主 | 2012-4-16 13:25 | 只看该作者
使用AD30M时钟,去做为FPGA采样的时钟,问题还是存在!!!
现在使用输入偏移约束,将约束FPGA采样前,数据和时钟的建立时间,不知道会好不!!!
在UCF中加入下面的约束,大家看看!
INST "ad_in<0>" TNM = ad_in;
INST "ad_in<1>" TNM = ad_in;
INST "ad_in<2>" TNM = ad_in;
INST "ad_in<3>" TNM = ad_in;
INST "ad_in<4>" TNM = ad_in;
INST "ad_in<5>" TNM = ad_in;
INST "ad_in<6>" TNM = ad_in;
INST "ad_in<7>" TNM = ad_in;
INST "ad_in<8>" TNM = ad_in;
INST "ad_in<9>" TNM = ad_in;
INST "ad_in<10>" TNM = ad_in;
INST "ad_in<11>" TNM = ad_in;
TIMEGRP "ad_in" OFFSET = IN 5 ns BEFORE "ad_clk" RISING;

使用特权

评论回复
34
lwq030736| | 2012-4-16 19:22 | 只看该作者
你这样全部一起约束成一样的,估计没什么用
你是第11位跑的慢,其他的跑的快,你就约束第11位,让他跑快点
或者让其他的跑慢点

使用特权

评论回复
35
fei530456072| | 2012-12-6 18:01 | 只看该作者
来参考一下,感谢楼主,感谢各位顶贴!

使用特权

评论回复
36
hawksabre| | 2012-12-6 21:29 | 只看该作者
个人觉得应该是时钟不同步导致的   建议将布局修改修改   同时确保时钟信号同步   呵呵

使用特权

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

本版积分规则