FPGA|CPLD|ASICwilliam hill官网
直播中

梁振福

10年用户 39经验值
擅长:可编程逻辑 嵌入式技术 处理器/DSP
私信 关注
[问答]

特权同学《FPGA/CPLD边学边练》一书中的疑问

在特权同学《FPGA/CPLD边学边练》一书中的SRAM读写测试实验,程序如下:module sram_test(                                clk,rst_n,led,
                                sram_addr,sram_wr_n,sram_data
                        );

input clk;                // 50MHz
input rst_n;        //低电平复位
output led;                // LED1

        // CPLD与SRAM外部接口
output[14:0] sram_addr;        // SRAM地址总线
output sram_wr_n;                // SRAM写选通
inout[7:0] sram_data;        // SRAM数据总线

//-------------------------------------------------------
reg[25:0] delay;        //延时计数器

always @ (posedge clk or negedge rst_n)
        if(!rst_n) delay <= 26'd0;
        else delay <= delay+1;        //不断计数,周期约为1.28s
       
//-------------------------------------------------------
reg[7:0] wr_data;        // SRAM写入数据总线       
reg[7:0] rd_data;        // SRAM读出数据
reg[14:0] addr_r;        // SRAM地址总线
wire sram_wr_req;        // SRAM写请求信号
wire sram_rd_req;        // SRAM读请求信号
reg led_r;                        // LED寄存器

assign sram_wr_req = (delay == 26'd9999);        //产生写请求信号
assign sram_rd_req = (delay == 26'd19999);        //产生读请求信号
       
always @ (posedge clk or negedge rst_n)
        if(!rst_n) wr_data <= 8'd0;
        else if(delay == 26'd29999) wr_data <= wr_data+1'b1;        //写入数据每1.28s自增1

always @ (posedge clk or negedge rst_n)
        if(!rst_n) addr_r <= 15'd0;
        else if(delay == 26'd29999) addr_r <= addr_r+1'b1;        //写入地址每1.28s自增1
       
always @ (posedge clk or negedge rst_n)
        if(!rst_n) led_r <= 1'b0;
        else if(delay == 26'd20099) begin        //每1.28s比较一次同一地址写入和读出的数据
                        if(wr_data == rd_data) led_r <= 1'b1;        //写入和读出数据一致,LED点亮
                        else led_r <= 1'b0;                                                //写入和读出数据不同,LED熄灭
                end
assign led = led_r;

//-------------------------------------------------------
`define        DELAY_80NS                (cnt==3'd7)

reg[2:0] cnt;        //延时计数器

always @ (posedge clk or negedge rst_n)
        if(!rst_n) cnt <= 3'd0;
        else if(cstate == IDLE) cnt <= 3'd0;
        else cnt <= cnt+1'b1;
                       
//------------------------------------
parameter        IDLE        = 4'd0,
                        WRT0        = 4'd1,
                        WRT1        = 4'd2,
                        REA0        = 4'd3,
                        REA1        = 4'd4;

reg[3:0] cstate,nstate;

always @ (posedge clk or negedge rst_n)
        if(!rst_n) cstate <= IDLE;
        else cstate <= nstate;

always @ (cstate or sram_wr_req or sram_rd_req or cnt)
        case (cstate)
                        IDLE: if(sram_wr_req) nstate <= WRT0;                //进入写状态
                                  else if(sram_rd_req) nstate <= REA0;        //进入读状态
                                  else nstate <= IDLE;
                        WRT0: if(`DELAY_80NS) nstate <= WRT1;
                                  else nstate <= WRT0;                                //延时等待160ns       
                        WRT1: nstate <= IDLE;                        //写结束,返回
                        REA0: if(`DELAY_80NS) nstate <= REA1;
                                  else nstate <= REA0;                                //延时等待160ns
                        REA1: nstate <= IDLE;                        //读结束,返回
                default: nstate <= IDLE;
                endcase
                       
//-------------------------------------

assign sram_addr = addr_r;        // SRAM地址总线连接

//-------------------------------------                       
reg sdlink;                                // SRAM数据总线控制信号

always @ (posedge clk or negedge rst_n)
        if(!rst_n) rd_data <= 8'd0;
        else if(cstate == REA1) rd_data <= sram_data;                //读出数据

always @ (posedge clk or negedge rst_n)
        if(!rst_n) sdlink <=1'b0;
        else
                case (cstate)
                        IDLE: if(sram_wr_req) sdlink <= 1'b1;                //进入连续写状态
                                  else if(sram_rd_req) sdlink <= 1'b0;        //进入单字节读状态
                                  else sdlink <= 1'b0;
                        WRT0: sdlink <= 1'b1;
                        default: sdlink <= 1'b0;
                        endcase

assign sram_data = sdlink ? wr_data : 8'hzz;        // SRA数据总线连接                       
assign sram_wr_n = ~sdlink;
                       
endmodule


我有一处不明,        “else if(cstate == REA1) rd_data <= sram_data;        ”这句说的是读出数据,但是此时        sdlink为0, sram_data应为高阻态(8‘hzz),所以rd_data怎么会等于wr_data??求大神解答~~~


回帖(5)

187336

2014-4-1 13:35:03
sdlink=1时,sram_data作为输出端,起到写ram的功能;
sdlink=0时,sram_data高阻态,作为输入端,起到读ram的作用。
举报

187336

2014-4-1 13:40:57
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报
  • 捕获.JPG

youzizhile

2014-4-4 17:13:09
楼上分析额很好,图文并茂
举报

梁振福

2014-4-11 22:59:30
引用: iweimo 发表于 2014-4-1 13:40
inout端口其实是一个三态门,如图所示,link_reg控制三态门为高阻态时,IO与data_in连接,作为输入。反之 ...

额  原来是这样~  之前我还以为data_in和data_out是指同一条路径,现在看来应该是两条不同的路径,但由同一个IO口控制而已......谢谢
举报

水木&随风

2014-4-19 09:19:41
真的是超级好用啊,赞一个
举报

更多回帖

发帖
×
20
完善资料,
赚取积分