搜索
bottom↓
回复: 14

一个读SRAM程序的问题。望各位兄弟进来瞧瞧,帮忙解决。

[复制链接]

出0入55汤圆

发表于 2010-8-9 12:15:02 | 显示全部楼层 |阅读模式
小弟刚用上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 [15:0] SRAM_data_in;
output [17:0] Addr_out;  //SRAM控制或者数据地址。

output [7:0] send_data_out;  //串口数据
output send_done;   //发送完毕标志位.
output WR;          //串口发送允许位。
input TI;           //串口发完一个字节标志位.  

reg [15:0] regSRAM_data;      
reg [7:0] regdata_send_out;
reg [7:0] coul;          //为什么等待4个时钟

reg nOE;         
reg [17:0] regAddr;
reg send_done;
reg WR;

reg [3:0] 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)没用呢?或者是我判断错误,是别的问题我没发现。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入55汤圆

 楼主| 发表于 2010-8-9 12:17:07 | 显示全部楼层
这个是串口发送模块。
/********************send*************************
**模块名称:send
**功能描述:UART的发送程序
**************************************************/
module send(
                        clk,                                                                        //时钟
                        clkout,                                                                        //输出
                        Datain,                                                                        //需要发送的一个字节数据
                        TXD,                                                                        //uart发送引脚       
                        TI,                                                                                //发送中断
                        WR                                                                                //写控制信号
                        );
input                        clk;                                                                //输入时钟
input                        WR;                                                                        //写信号
input        [7:0]        Datain;                                                                //发送的一字节数据
output                        clkout;                                                                //输出时钟
output                        TXD,TI;                                                                //串行数据,发送中断

reg                [9:0]        Datainbuf,Datainbuf2;                                //发送数据缓存
reg                         WR_ctr,TI,txd_reg;                                        //写标志、中断标志、一位发送寄存器
reg                [3:0]        bincnt;                                                                //发送数据计数器
reg                [15:0]        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[7:0],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[0];                                //从最低位开始发送
                                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

出0入55汤圆

 楼主| 发表于 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 [15:0] SRAM_data_in;
output [17:0] Addr_out;

output TXD;

wire WR;
wire TI;
wire [7:0] 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

出0入55汤圆

 楼主| 发表于 2010-8-9 12:20:43 | 显示全部楼层
这用串口助手接收时。按一下按键。就有数据发送。放开就没。数据量看按键按下去的时间长短。并没有出现发送coutner个字节。为什么呢?真是百思不得其解。

出0入55汤圆

 楼主| 发表于 2010-8-9 14:23:56 | 显示全部楼层
搞定了。原来是时钟搞错了。SRAM_RE U2(.clk(clk_48M)太快了, 改成SRAM_RE U2(.clk(clkout),就行了。

出0入0汤圆

发表于 2010-8-9 20:18:50 | 显示全部楼层
呵呵

出0入0汤圆

发表于 2010-8-9 21:33:53 | 显示全部楼层
解决就好

出0入0汤圆

发表于 2010-8-9 23:59:30 | 显示全部楼层
恭喜

出0入0汤圆

发表于 2010-8-10 08:31:47 | 显示全部楼层
恭喜,学习了

出0入0汤圆

发表于 2010-8-10 09:41:36 | 显示全部楼层
学习学习!

出0入0汤圆

发表于 2010-12-14 10:10:42 | 显示全部楼层
呵呵,学习中……

出0入0汤圆

发表于 2010-12-14 11:15:14 | 显示全部楼层
不错,解决了就好啊

出0入0汤圆

发表于 2010-12-15 11:13:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-24 15:25:07 | 显示全部楼层
呵呵,思考过为何48M的不行吗?
还有个疑问,那个SRAM的时序图,可以发下吗?

出0入0汤圆

发表于 2010-12-24 15:35:13 | 显示全部楼层
学习
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 15:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表