一个读SRAM程序的问题。望各位兄弟进来瞧瞧,帮忙解决。
小弟刚用上FPGA,写了一个读取SRAM并发送串口的程序。出现了一个搞不定的问题。串口程序用的是ZLG的原码,应该没问题。但是整个用串口助手接收时。按一下按键。就有数据发送。放开就没。数据量看按键按下去的时间长短。并没有出现发送coutner个字节。为什么呢?真是百思不得其解。// SRAM_RE.v
module SRAM_RE(clk,rst,re_en,nCE,nOE,nUB,nLB,SRAM_data_in,Addr_out,send_data_out,send_done,WR,TI);
input clk;
input rst;
input re_en; //读允许位。
output nCE;
output nOE;
output nUB;
output nLB;
input SRAM_data_in;
output Addr_out;//SRAM控制或者数据地址。
output send_data_out;//串口数据
output send_done; //发送完毕标志位.
output WR; //串口发送允许位。
input TI; //串口发完一个字节标志位.
reg regSRAM_data;
reg regdata_send_out;
reg coul; //为什么等待4个时钟
reg nOE;
reg regAddr;
reg send_done;
reg WR;
reg state; //状态标志。
wire nCE;
wire nUB;
wire nLB;
integer counter; //发送字节计数
parameter init_mode = 4'b0000;
parameter wait_re_en = 4'b0001;
parameter read_SRAM_data = 4'b0010;
parameter send_data_low_ready = 4'b0011;
parameter send_data_low = 4'b0100;
parameter send_data_high_ready = 4'b0101;
parameter send_data_high = 4'b0110;
parameter is_send_over = 4'b0111;
assign nCE = 1'b0;
assign nUB = 1'b0;
assign nLB = 1'b0;
assign send_data_out = regdata_send_out;
assign Addr_out = regAddr;
always@(posedge clk)
begin
if(rst)
begin
state <= init_mode;
end//if(rst)
else
begin
case(state)
init_mode:
begin
counter <= 0;
nOE <= 1'b1;
send_done <= 1'b1;
regAddr <= 8'd0;
WR <= 1'b0;
regdata_send_out <= 8'd0;
state <= wait_re_en;
end//init_mode
wait_re_en: //等待按键。按键按下去为高。re_en连接外部一个按键
begin
if(re_en)
begin
nOE <= 1'b0;
send_done <= 1'b0;
state <= read_SRAM_data;
end//if(re_en)
else state <= wait_re_en;
end//wait_re_en
read_SRAM_data:
begin
regSRAM_data <= SRAM_data_in;
regAddr <= regAddr + 1'b1;
counter <= counter + 1;
state <= send_data_low_ready;
end//read_SRAM_data
send_data_low_ready:
begin
regdata_send_out <= regSRAM_data;
state <= send_data_low;
end//send_data_low_ready
send_data_low:
begin
WR <= 1'b1;
if(coul>=8'd4)
begin
coul <= coul + 1;
WR <= 1'b0;
if(TI==1'b1)
begin
state <= send_data_high_ready;
coul <= 8'd0;
end//if(TI==1'b1)
else
state <= send_data_low;
end//if(coul>=8'd4)
else
begin
state <= send_data_low;
coul <= coul + 1;
end//else
end//send_data_low
send_data_high_ready:
begin
regdata_send_out <= (regSRAM_data>>8);
state <= send_data_high;
end//send_data_high_ready
send_data_high:
begin
WR <= 1'b1;
if(coul>=8'd4)
begin
coul <= coul + 1;
WR <= 1'b0;
if(TI==1'b1)
begin
state <= is_send_over;
coul <= 8'd0;
end//if(TI==1'b1)
else
state <= send_data_high;
end//if(coul>=8'd4)
else
begin
state <= send_data_high;
coul <= coul + 1;
end//else
end//send_data_high
is_send_over:
begin
if(counter==2000)
begin
state <= init_mode; //<----------------------好像每次都进来这里。和counter值无关。
end//ifif(counter==2000)
else
begin
state <= read_SRAM_data; //<----------------------所以这里根本没执行。为什么?
end//else
end//is_send_over
default: state <= init_mode;
endcase
end//else
end//always
endmodule
这个问题弄了两天了。无论怎么改都是这样。各位大虾帮帮忙。为什么if(counter==2000)没用呢?或者是我判断错误,是别的问题我没发现。 这个是串口发送模块。
/********************send*************************
**模块名称:send
**功能描述:UART的发送程序
**************************************************/
module send(
clk, //时钟
clkout, //输出
Datain, //需要发送的一个字节数据
TXD, //uart发送引脚
TI, //发送中断
WR //写控制信号
);
input clk; //输入时钟
input WR; //写信号
input Datain; //发送的一字节数据
output clkout; //输出时钟
output TXD,TI; //串行数据,发送中断
reg Datainbuf,Datainbuf2; //发送数据缓存
reg WR_ctr,TI,txd_reg; //写标志、中断标志、一位发送寄存器
reg bincnt; //发送数据计数器
reg cnt; //计数器
wire clk_equ; //分频时钟
parameter cout = 5000; //根据具体的时钟来设定分频系数
//这里是48M时钟,波特率选择是9600,所以分频系数为48000000/9600= 5000;
/*************波特率发生进程****************************/
always@(posedge clk)
begin
if(clk_equ)
cnt = 16'd0;
else
cnt=cnt+1'b1;
end
assign clk_equ = (cnt == cout);
assign clkout = clk_equ;
/*************读数据到缓存进程****************************/
always@(posedge clk)
begin
if(WR)
begin
Datainbuf = {1'b1,Datain,1'b0}; //读入数据,并把缓存组成一帧数据,10位
WR_ctr = 1'b1; //置开始标志位
end
else if(TI==0)
WR_ctr = 1'b0;
end
/*************主程序进程****************************/
always@(posedge clk)
begin
if(clk_equ)
begin
if(WR_ctr==1||bincnt<4'd10) //发送条件判断,保证发送数据的完整性
begin
if(bincnt<4'd10)
begin
txd_reg =Datainbuf2; //从最低位开始发送
Datainbuf2 = Datainbuf>>bincnt; //移位输出
bincnt = bincnt+4'd1; //发送数据位计数
TI = 1'b0;
end
else
bincnt = 4'd0;
end
else
begin //发送完毕或者处于等待状态时TXD和TI为高
txd_reg = 1'b1;
TI = 1'b1;
end
end
end
assign TXD = txd_reg; //TXD连续输出
endmodule 这个是顶层模块
/************* top *************************
**模块名称:top
**功能描述:
**创建日期:
**修改日期:
***************************************************/
module read_top(clk_48M,rst,nCE,nOE,nUB,nLB,SRAM_data_in,Addr_out,TXD,re_en,send_done);
input clk_48M;
input rst;
input re_en;
output send_done;
output nCE,nOE,nUB,nLB;
input SRAM_data_in;
output Addr_out;
output TXD;
wire WR;
wire TI;
wire senddata;
send U1(.clk(clk_48M),
.Datain(senddata),
.TXD(TXD),
.TI(TI),
.WR(WR));
SRAM_RE U2(.clk(clk_48M),
.rst(rst),
.re_en(re_en),
.nCE(nCE),
.nOE(nOE),
.nUB(nUB),
.nLB(nLB),
.SRAM_data_in(SRAM_data_in),
.Addr_out(Addr_out),
.send_data_out(senddata),
.send_done(send_done),
.WR(WR),
.TI(TI));
endmodule 这用串口助手接收时。按一下按键。就有数据发送。放开就没。数据量看按键按下去的时间长短。并没有出现发送coutner个字节。为什么呢?真是百思不得其解。 搞定了。原来是时钟搞错了。SRAM_RE U2(.clk(clk_48M)太快了, 改成SRAM_RE U2(.clk(clkout),就行了。 呵呵 解决就好 恭喜 恭喜,学习了 学习学习! 呵呵,学习中…… 不错,解决了就好啊 mark 呵呵,思考过为何48M的不行吗?
还有个疑问,那个SRAM的时序图,可以发下吗? 学习
页:
[1]