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

当然要实现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贴上来一点缩进都没有了。
这里看代码太累了
谢谢您~真的很是受益匪浅!
看来代码,学习了!
状态机用三段式来写,一段式的状态机会出问题,而且很乱
