jssd 发表于 2010-8-9 12:15:02

一个读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)没用呢?或者是我判断错误,是别的问题我没发现。

jssd 发表于 2010-8-9 12:17:07

这个是串口发送模块。
/********************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

jssd 发表于 2010-8-9 12:18:22

这个是顶层模块
/************* 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

jssd 发表于 2010-8-9 12:20:43

这用串口助手接收时。按一下按键。就有数据发送。放开就没。数据量看按键按下去的时间长短。并没有出现发送coutner个字节。为什么呢?真是百思不得其解。

jssd 发表于 2010-8-9 14:23:56

搞定了。原来是时钟搞错了。SRAM_RE U2(.clk(clk_48M)太快了, 改成SRAM_RE U2(.clk(clkout),就行了。

li20030505 发表于 2010-8-9 20:18:50

呵呵

barryyan2007 发表于 2010-8-9 21:33:53

解决就好

caozhu 发表于 2010-8-9 23:59:30

恭喜

wanwzy 发表于 2010-8-10 08:31:47

恭喜,学习了

vtfengxingzhe 发表于 2010-8-10 09:41:36

学习学习!

above2009 发表于 2010-12-14 10:10:42

呵呵,学习中……

guke 发表于 2010-12-14 11:15:14

不错,解决了就好啊

lsw0136 发表于 2010-12-15 11:13:11

mark

lovexiaona 发表于 2010-12-24 15:25:07

呵呵,思考过为何48M的不行吗?
还有个疑问,那个SRAM的时序图,可以发下吗?

AG17 发表于 2010-12-24 15:35:13

学习
页: [1]
查看完整版本: 一个读SRAM程序的问题。望各位兄弟进来瞧瞧,帮忙解决。