微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 求助各位大大怎么用Verilog实现这样的时序呢

求助各位大大怎么用Verilog实现这样的时序呢

时间:10-02 整理:3721RD 点击:
想使用FPGA产生以下时序来驱动一个线阵的探测器芯片



当然要实现CLK是很容易的 只要把系统时钟Mclk(50MHZ)分频就可以产生希望的40khz的CLK 关于RESET我的想法是使用状态机
但实现起来发现并不能产生相应的波形 希望大家看看程序的问题
module XB8804(Mclk, nRst,
               FPGA_CLK, FPGA_RESET
    );
input Mclk,nRst;
output FPGA_CLK,FPGA_RESET;
reg FPGA_CLK;
reg FPGA_RESET;
reg[9:0] FPGA_CLK_CNT;
reg [10:0] clk_cnt;
reg[3:0] state;
wire Scan_Flag; //扫描标志位
parameter IDLE=4'b1000,
          RESET_L1=4'b0100,
    RESET_L2=4'b0010,
    RESET_H=4'b001;
assign Scan_Flag=1;//Scan_Flag应该是由外部的控制单元给过来 这里直接赋值了
        
always @(negedge nRst or posedge Mclk)
if(!nRst)   begin
       clk_cnt<=0;
       FPGA_CLK<=0;
   FPGA_RESET<=1;
   FPGA_CLK_CNT <= 0;
   state <= IDLE;
             end
else  begin     
    if(clk_cnt==11'd625)
            begin
      clk_cnt<=0;
      FPGA_CLK<=~FPGA_CLK;
      FPGA_CLK_CNT <= FPGA_CLK_CNT+1;
      end
    else
            clk_cnt<=clk_cnt+11'd1;  
   
case(state)
IDLE:
begin  
  FPGA_CLK<=1;
    FPGA_RESET<=1;  
   if(Scan_Flag==1)
     begin   
     state<=RESET_L1;
     FPGA_CLK_CNT <= 0;
       end
else state<=IDLE;
end
RESET_L1:
begin
FPGA_RESET<=0;
if(FPGA_CLK_CNT==15)
       begin
   state<=RESET_H;
   end
else state<=RESET_L1;
end
RESET_H:
begin
begin
   FPGA_RESET<=1;
   if(FPGA_CLK_CNT==10'd529)
begin
state<=RESET_L2;
   end
   else state<=RESET_H;
end
RESET_L2:
begin
FPGA_RESET<=0;
   if(FPGA_CLK_CNT==10'd7)
   begin
if(Scan_Flag==1)
     state<=RESET_L1;
else state<=IDLE;
   end
else state<=RESET_L2;
end
default:state<=IDLE;
endcase
end
endmodule

怎么全写在一个always块里面啊?乱!   RESET一开始是要保持15个周期的低电平?你的FPGA_CLK_CNT信号每个周期+2;



   具体应该是这样的 :系统上电后 CLK和RESET都保持高电平。如果检测到Scan_Flag变为高,就启动分频器工作,把50M的系统时钟Mclk分频成40Khz,同时RESET拉低,当对CLK计数到达15后,RESET再拉高(17+128*4)个CLK周期,之后再拉低6.5个CLK周期。之后再判断Scan_Flag: 高就继续这一过程,低就结束了。因为人为把Scan_Flag=1,那么这一过程应该一直进行。
我在示波器测得RESET信号是均匀周期的方波。
那么我这么写可以吗 恳请高手不吝指导 关键是怎么生成我想要的3个不同周期的RESET信号呢 我的状态机设定有问题吗 我感觉是不是计数不对呢 如果FPGA_CLK_CNT每次是加2 应该怎么改呢
module XB8804(Mclk, nRst,
               FPGA_CLK, FPGA_RESET
    );
input Mclk,nRst;
output FPGA_CLK,FPGA_RESET;
reg FPGA_CLK;
reg FPGA_RESET;
reg[9:0] FPGA_CLK_CNT;
reg [10:0] clk_cnt;
reg[3:0] state;
wire Scan_Flag;
parameter IDLE=4'b1000,
          RESET_L1=4'b0100,
    RESET_L2=4'b0010,
    RESET_H=4'b001;
   
assign Scan_Flag=1;
        
always @(negedge nRst or posedge Mclk)
if(!nRst)   begin
       clk_cnt<=0;
       FPGA_CLK<=0;
  // FPGA_RESET<=1;
   FPGA_CLK_CNT <= 0;
             end
else  begin     
    if(clk_cnt==11'd625)
            begin
      clk_cnt<=0;
      FPGA_CLK<=~FPGA_CLK;
      FPGA_CLK_CNT<= FPGA_CLK_CNT+1;
      end
    else
            clk_cnt<=clk_cnt+11'd1;
  end  

always @(negedge nRst or posedge Mclk)
if(!nRst)   begin
       FPGA_RESET<=1;
      // FPGA_CLK<=1;
   state <= IDLE;
             end
else        
case(state)
IDLE:
begin  
// FPGA_CLK<=1;
    FPGA_RESET<=1;  
   if(Scan_Flag==1)
     begin   
     state<=RESET_L1;
   // FPGA_CLK_CNT <= 0;
       end
else state<=IDLE;
end
RESET_L1:
begin
FPGA_RESET<=0;
if(FPGA_CLK_CNT==10'd15)
       begin
   state<=RESET_H;
   end
else state<=RESET_L1;
end
RESET_H:
begin
   FPGA_RESET<=1;
   if(FPGA_CLK_CNT==10'd544)
begin
state<=RESET_L2;
   end
   else state<=RESET_H;
end
RESET_L2:
begin
FPGA_RESET<=0;
   if(FPGA_CLK_CNT==10'd551)
   begin
if(Scan_Flag==1)
     state<=RESET_L1;
else state<=IDLE;
   end
else state<=RESET_L2;
end
default:state<=IDLE;
endcase
endmodule



   我修改了一下,写verilog时要想着对应的电路是什么样子的;module XB8804(Mclk, nRst,
               FPGA_CLK, FPGA_RESET
              );
input Mclk,nRst;
output FPGA_CLK,FPGA_RESET;
reg FPGA_CLK;
reg FPGA_RESET;
reg FPGA_CLK_D1,FPGA_CLK_D2;
reg[10:0] FPGA_CLK_CNT;
reg [11:0] clk_cnt;
reg[3:0] present,next;
wire FPGA_CLK_Rising;
wire FPGA_CLK_Falling;
wire Scan_Flag;
parameter IDLE=4'b1000,
          RESET_L1=4'b0100,
  RESET_H=4'b0010,
      RESET_L2=4'b0001;
      
assign Scan_Flag=1;
always @(negedge nRst or posedge Mclk)     //frequency division
if(!nRst)  
begin
clk_cnt<=0;
FPGA_CLK<=1;
end
else if(clk_cnt==11'd625)
begin
clk_cnt<=11'd0;
    FPGA_CLK<=~FPGA_CLK;
end
else
clk_cnt<=clk_cnt+11'd1;
always@(negedge nRst or posedge Mclk)
if(!nRst)
begin
FPGA_CLK_D1<=1'b0;
FPGA_CLK_D2<=1'b0;
end
else
begin
FPGA_CLK_D1<=FPGA_CLK;
FPGA_CLK_D2<=FPGA_CLK_D1;
end

assign FPGA_CLK_Rising=FPGA_CLK_D1&(~FPGA_CLK_D2);
assign FPGA_CLK_Falling=FPGA_CLK_D2&(~FPGA_CLK_D1);
always@(negedge nRst or posedge Mclk)
if(!nRst)
present<=IDLE;
else if(FPGA_CLK_Rising)
present<=next;


always@(posedge Mclk)
if(present==IDLE)
FPGA_CLK_CNT<=11'd0;
else if(FPGA_CLK_Rising==1'd1 || FPGA_CLK_Falling==1'd1)
FPGA_CLK_CNT<=FPGA_CLK_CNT+11'd1;

always@(Scan_Flag or present or FPGA_CLK_CNT)
case(present)
IDLE:
begin
FPGA_RESET<=1'd1;
if(Scan_Flag==1'b1)
next<=RESET_L1;
else
next<=IDLE;
end
RESET_L1:
begin
FPGA_RESET<=1'd0;
if(FPGA_CLK_CNT<11'd28)
next<=RESET_L1;
else
next<=RESET_H;
end
RESET_H:
begin
FPGA_RESET<=1'd1;
if(FPGA_CLK_CNT<11'd1056)
next<=RESET_H;
else
next<=RESET_L2;
end
RESET_L2:
begin
FPGA_RESET<=1'd0;
if(FPGA_CLK_CNT<11'd1069)
next<=RESET_L2;
else
next<=IDLE;
end
default:
begin
FPGA_RESET<=1'd1;
next<=IDLE;
end
endcase
endmodule

状态机推荐2段或者三段式
另,推荐lz使用仿真的方法调试代码,这样对时序的理解会快一些
另给管理员提个建议,能不能借鉴下别的网站,可以在帖子里集成类似代码编辑工具之类
的东东,这样代码会更好看一些?

怎么我写的verilog贴上来一点缩进都没有了。

这里看代码太累了



    谢谢您~真的很是受益匪浅!

看来代码,学习了!

状态机用三段式来写,一段式的状态机会出问题,而且很乱

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top