赞
踩
flash解释:
W25Q128BV-datasheet中文资料 - 夜下青灯 - 博客园
在芯片资料上极性和相位一般表示为CPOL(Clock POLarity)和CPHA(Clock PHAse), 极性和相位组合成4种工作模式。
CPOL CPHA
MODE0 0 0
MODE1 0 1
MODE2 1 0
MODE3 1 1
CPOL: SPI空闲时的时钟信号电平(1:高电平, 0:低电平)
CPHA: SPI在时钟第几个边沿采样(1:第二个边沿开始, 0:第一个边沿开始
MODE0 :时钟默认是0,第0个沿
MODE1 :时钟默认是1,第1个沿
目的实现最高速率133MHz
SDR:在上升沿采样输入数据,在下降沿输出数据。
DDR:command/instruction还是在上升沿采样输入数据,
在command/instruction完成之后的第一个上升沿采样address/rxdata输入数据,
紧接着是下降沿采样输入数据。
在dummy完成后的第一个下降沿输出数据是。
command protocol
command =8bit instruction + address + modifier + latency +data transfer
1-1-1 command protocol: single bit data 传输 instruction+addr+data
之前本计划让时钟一直有效,控制CS#来操作flash,结果发现行不通,因为一个完整的command不允许中途CS#变化。
因为flash需要兼容x1/2/4模式,只能通过 instruction来区分不同模式,
如果 instruction也采用4线模式,那么在x1/x2是无法识别的。
如果 instruction都采用x1,那么兼容x1/2/4都可识别。
FPGA在address之后发送 instruction modifer bits,暗示下一个命令与当前命令一样,下一次就不用传输 instruction,只需要传输address+ mode bits;
mode bits 发起或者结束 Continuous Read Mode;
所有的都是MSB高字节先进入flash











通过特定的instruction。
Size=1024B ,分成4个regions.如果regions没有保护和锁定,那么可以正常读写。CR1NV[5:2]:LockBits,只能写入一次OTP(OneTimePragram),写入后永久有效。
region2&3可以通过PR(ProtectionRsgister)临时保护不被擦写,操作IRP寄存器[2],当密码正确可以解除保护。
通过RDID Command(9FH)来读取ID值。
RSFDP Command (5AH)
SFDP的数据在出厂时就被固定住,无法修改,只供查询使用。厂商识别码等一系列的功能和参数信息
https://blog.csdn.net/bingquan3333/article/details/81872475
https://www.taterli.com/2984/
数字表示的是使用的线宽,顺序是
instruction-address-data
Single 1-1-1 instruction (SI) + addr (SI) + data (SO )
Dual O 1-1-2 instruction (SI) + addr (SI) + data (IO0&IO1)
Dual IO 1-2-2 ...
Quad O 1-1-4 ...
Quad IO 1-4-4 ...
QPI 4-4-4 ...
1.在上电或者复位flash芯片之后,给volatile寄存器提供初始值。
2.保护bits一次写入
配置寄存器1的内容:
1.设置Security Rigion Lock Bits
2.设置默认Quad
配置寄存器2的内容:
1.QPI模式
2.默认地址长度24|32
对FLASH进行读写擦除操作。
可以读任意1B,读完当前Byte只要CS#没有拉高,不用重新给地址,地址会自动+1,后续数据会持续移出。
read和fastread的区别在于支持的最大的时钟频率不同。
READ

FAST_READ

可以
page program 02H
single Byte program必须先WREN使能;
Page Program

sector Erase 20H
Half Block Erase 52H
Block Erase D8H
擦除需要时间,FPGA通过查看WIP bit在状态寄存器1 来确定擦除是否完成。1:未完成,0:完成











![]()




PP命令,每次只能连续写入1page 256Byte
![]()

![]()

![]()

![]()

![]()

![]()

-
- //spi_ctrl.v
- //0H 发送数据(写)/接收数据(读)
- //1H 命令(写)/状态(读)
- //2H 地址低(写) add_l
- //3H 地址中(写) add_m
- //4H 地址高(写) add_h
- // 写数据到地址0x40_0000:
- // 1.告知FPGA地址:先写40h到4H地址,然后写00h到3H地址,最后写00h到2H地址;
- // 2.告知FPGA数据:将要写的数据写入0H地址;
- // 3.告知FPGA命令:将写命令告知FPGA;
- //拆分成两部分:
- //1. 控制数据的产生
- //2. 单Byte数据发送
- `timescale 1ns/100ps
- `define SIM_OPEN 1
- module spi_ctrl (
- input clk ,
- input rst ,
- //管脚信号
- output spi_clk ,
- output spi_csn ,
- input spi_din ,
- output spi_dout ,
- //内部管理口
- input m_cs ,
- input m_wr ,
- input [2:0] m_addr ,
- input [7:0] m_din ,
- output reg [7:0] m_dout
- );
-
- reg [7:0] tx_data0 ;//待发送的数据寄存器
- reg [7:0] rx_data0 ;//已接收的数据寄存器
- reg [7:0] cmd ;//命令寄存器
- reg [7:0] state ;//状态寄存器
- reg [7:0] add_h ;//地址高寄存器
- reg [7:0] add_m ;//地址中寄存器
- reg [7:0] add_l ;//地址低寄存器
-
- //检测到操作
- wire rd_data ;
- wire wr_data ;
- reg wr_data_1d;
- wire rd_stata ;
- wire wr_cmd ;
- wire rd_add_h ;
- wire rd_add_m ;
- wire rd_add_l ;
- wire wr_add_h ;
- wire wr_add_m ;
- wire wr_add_l ;
-
- reg spi_clk_int ;
- wire spi_csn_int ;//由外部控制,因为一次操作不一定只有1B,此处透传
- wire spi_din_int ;
- reg spi_dout_int ;
-
- // ST:state状态机
- reg ST_cs ;//当前1B发送完毕
- reg ST_wr ;//当前1B发送完毕
- reg [7:0] ST_wdata ;//当前1B发送完毕
- wire ST_wrvld ;//当前1B发送完毕
- wire [7:0] ST_rdata ;//当前收到的1B有效数据
-
- parameter div_max = 8'd4 ;
- reg [2:0] clk_cnt ;
- reg clk_en ;//每次分频计数==0的这一拍有效
- //判断是什么操作
- assign rd_data = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b0,3'd0})?1'b1 :1'b0 ;
- assign wr_data = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b1,3'd0})?1'b1 :1'b0 ;
- assign rd_stata = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b0,3'd1})?1'b1 :1'b0 ;
- assign wr_cmd = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b1,3'd1})?1'b1 :1'b0 ;
- assign rd_add_h = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b0,3'd2})?1'b1 :1'b0 ;
- assign rd_add_m = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b0,3'd3})?1'b1 :1'b0 ;
- assign rd_add_l = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b0,3'd4})?1'b1 :1'b0 ;
- assign wr_add_h = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b1,3'd2})?1'b1 :1'b0 ;
- assign wr_add_m = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b1,3'd3})?1'b1 :1'b0 ;
- assign wr_add_l = ({m_cs,m_wr,m_addr[2:0]} == {1'b1,1'b1,3'd4})?1'b1 :1'b0 ;
- //锁存数据到寄存器
- always @(posedge clk or posedge rst)if(rst) tx_data0 <=#1 8'b0;else if(wr_data )tx_data0 <=#1 m_din;
- always @(posedge clk or posedge rst)if(rst) cmd <=#1 8'b0;else if(wr_cmd )cmd <=#1 m_din;
- always @(posedge clk or posedge rst)if(rst) add_h <=#1 8'b0;else if(wr_add_h)add_h <=#1 m_din;
- always @(posedge clk or posedge rst)if(rst) add_m <=#1 8'b0;else if(wr_add_m)add_m <=#1 m_din;
- always @(posedge clk or posedge rst)if(rst) add_l <=#1 8'b0;else if(wr_add_l)add_l <=#1 m_din;
-
- always @(posedge clk or posedge rst)if(rst) wr_data_1d <=#1 1'b0;else wr_data_1d <=#1 wr_data;
- // 读数据接口
- always @(posedge clk or posedge rst)begin
- if(rst)
- m_dout <=#1 8'b0;
- else begin
- case({rd_data,rd_stata,rd_add_h,rd_add_m,rd_add_l})
- 5'b00001: m_dout <=#1 add_l;
- 5'b00010: m_dout <=#1 add_m;
- 5'b00100: m_dout <=#1 add_h;
- 5'b01000: m_dout <=#1 state;
- 5'b10000: m_dout <=#1 rx_data0;
- default : m_dout <=#1 8'b0;
- endcase
- end
- end
-
- parameter NOP = 8'hff;
- parameter WREN = 8'h06;//md0
- parameter WRDI = 8'h04;//md0
- parameter RDSR = 8'h05;//md6
- parameter WRSR = 8'h01;//md6
- parameter RDCMD = 8'h03;//md7
- parameter F_RD = 8'h0B;//md8
- parameter PP = 8'h02;//md4
- parameter SE = 8'hD8;//md9
- parameter BE = 8'hC7;//md0
- parameter DP = 8'hB9;//md0
- parameter RES = 8'hAB;//md0
- parameter RDID = 8'h9F;//md6
-
- wire md0,md1,md2,md3,md4,md5,md6,md7,md8,md9,mdstop;
- assign md0 = (cmd==WREN)|(cmd==WRDI)|(cmd==BE)|(cmd==DP)|(cmd==RES) ;
- assign md4 = (cmd==PP);
- assign md6 = (cmd==RDSR)|(cmd==WRSR)|(cmd==RDID);
- assign md7 = (cmd==RDCMD);
- assign md8 = (cmd==F_RD);
- assign md9 = (cmd==SE);
- assign mdstop = (cmd==NOP);
- //判断CMD的总体路径:In/out wr 都是fpga 角度
- //0. md0 : cmd
- //1. md1 : cmd+wdata--nouse
- //2. md2 : cmd+addr+wdata--nouse
- //3. md3 : cmd+wdata+...--nouse
- //4. md4 : cmd+addr+wdata+...
- //5. md5 : cmd+rdata--nouse
- //6. md6 : cmd+rdata+...
- //7. md7 : cmd+addr+rdata+...
- //8. md8 : cmd+addr+dummy+rdata+rdata+...
- //9. md9 : cmd+addr
- //定义设计中使用到的参数
- parameter DLY = 1;
- `ifdef SIM_OPEN
- parameter IDLE = "IDLE ",
- SDCMD = "SDCMD ",
- SDDATA = "SDDATA ",
- SDADDH = "SDADDH ",
- SDADDM = "SDADDM ",
- SDADDL = "SDADDL ",
- SDDMY = "SDDMY ",
- RXDATA = "RXDATA ";
- reg[127:0] cur_state,next_state,cur_state_1d;
- `else
- parameter IDLE = 8'b00000000,
- SDCMD = 8'b00000001,
- SDDATA= 8'b00000010,
- SDADDH= 8'b00000100,
- SDADDM= 8'b00001000,
- SDADDL= 8'b00010000,
- SDDMY = 8'b00100000,
- RXDATA= 8'b01000000;
- reg[7:0] cur_state,next_state,cur_state_1d;
- `endif
- wire ST_change;
- assign ST_change = cur_state_1d != cur_state;
- always @(posedge clk) cur_state_1d <= #DLY cur_state;
- //第一段状态转移
- always@(posedge clk or negedge rst)begin
- if(rst == 1'b1)begin
- cur_state <= #DLY IDLE;
- end else begin
- cur_state <= #DLY next_state;
- end
- end
- //第二段产生下一状态 数据流检测序列状态变化
- always@(*)begin
- if(rst == 1'b1)begin
- next_state = IDLE;
- end
- else begin
- case(cur_state)
- IDLE:
- begin
- if(md0|md4|md6|md7|md8|md9)
- next_state =SDCMD;
- else
- next_state = IDLE;
- end
- SDCMD:
- begin
- if((md4|md7|md8|md9) &ST_wrvld)
- next_state = SDADDH;
- else if((md0&ST_wrvld)|mdstop)
- next_state = IDLE;
- else if(md6&ST_wrvld)
- next_state = RXDATA;
- else
- next_state = SDCMD;
- end
- SDDATA:
- begin
- if(mdstop)
- next_state = IDLE;
- else
- next_state = SDDATA;
- end
- SDADDH:
- begin
- if(ST_wrvld)
- next_state = SDADDM;
- else
- next_state = SDADDH;
- end
- SDADDM:
- begin
- if(ST_wrvld)
- next_state =SDADDL;
- else
- next_state = SDADDM;
- end
- SDADDL:
- begin
- if(md8&ST_wrvld)
- next_state = SDDMY;
- else if(md7 &ST_wrvld)
- next_state = RXDATA;
- else if(md4 &ST_wrvld)
- next_state = SDDATA;
- else if(md9 &ST_wrvld)
- next_state = IDLE;
- else
- next_state = SDADDL;
- end
- SDDMY:
- begin
- if(ST_wrvld)
- next_state = RXDATA;
- else
- next_state = SDDMY;
- end
- RXDATA:
- begin
- if(mdstop)
- next_state = IDLE;
- else
- next_state = RXDATA;
- end
- default:begin
- next_state = IDLE;
- end
- endcase
- end
- end
- // rx_data0
- always @(posedge clk or posedge rst)begin
- if(rst)
- rx_data0 <=#1 8'b0;
- else if( (cur_state==RXDATA) & ST_wrvld)
- rx_data0 <=#1 ST_rdata;
- end
- // ST_wdata
- always @(posedge clk or posedge rst)begin
- if(rst)
- ST_wdata <=#1 8'b0;
- else if( cur_state==SDCMD )
- ST_wdata <=#1 cmd;
- else if( cur_state==SDADDH )
- ST_wdata <=#1 add_h;
- else if( cur_state==SDADDM )
- ST_wdata <=#1 add_m;
- else if( cur_state==SDADDL )
- ST_wdata <=#1 add_l;
- else if( cur_state==SDDATA )
- ST_wdata <=#1 tx_data0;
- end
- // ST_cs
- always @(posedge clk or posedge rst)begin
- if(rst)
- ST_cs <=#1 1'b0;
- else if( cur_state==IDLE )
- ST_cs <=#1 1'b0;
- else if( ST_change )
- ST_cs <=#1 1'b1;
- else if( (cur_state==SDDATA)&wr_data_1d )
- ST_cs <=#1 1'b1;
- else if( (cur_state==RXDATA)&rd_data )
- ST_cs <=#1 1'b1;
- else if( ST_cs==1'b1 )
- ST_cs <=#1 1'b0;
- end
- // SB_wr
- always @(posedge clk or posedge rst)begin
- if(rst)
- ST_wr <=#1 1'b1;
- else if( cur_state==RXDATA )
- ST_wr <=#1 1'b0;
- else
- ST_wr <=#1 1'b1;
- end
- // state
- wire busy;
- reg SDEmy;//发送空
- reg RXFull;//接收有数据
- reg WaitData;//等待写入新数据
-
- assign busy = (cur_state==IDLE)?1'b0:1'b1;
- // WaitData
- always @(posedge clk or posedge rst)begin
- if(rst)
- WaitData <=#1 1'b0;
- else if((cur_state==SDDATA)&ST_wrvld )
- WaitData <=#1 1'b1;
- else if((cur_state!=SDDATA))
- WaitData <=#1 1'b0;
- end
- // SDEmy
- always @(posedge clk or posedge rst)begin
- if(rst)
- SDEmy <=#1 1'b0;
- else if((cur_state==SDDATA)&ST_wrvld )
- SDEmy <=#1 1'b1;
- else if(wr_data)
- SDEmy <=#1 1'b0;
- end
- // RXFull
- always @(posedge clk or posedge rst)begin
- if(rst)
- RXFull <=#1 1'b0;
- else if((cur_state==RXDATA)&ST_wrvld )
- RXFull <=#1 1'b1;
- else if(rd_data)
- RXFull <=#1 1'b0;
- end
-
-
- always @(posedge clk or posedge rst)begin
- if(rst)
- state <=#1 8'b0;
- else
- state <=#1 {4'b0,WaitData,RXFull,SDEmy,busy};
- end
-
- assign spi_csn_int = (cur_state==IDLE)?1'b1:1'b0;
- //通过写入命令触发FPGA发送时序操作FLASH
-
-
-
-
-
- //--------------单Byte数据发送 Single Byte 简称SB--------------
- // 外部输出是SPI
- // S25FL128L mode0|3 此代码实现mode0
- // FLASH在上升沿采样FPGA发出的数据,--要求:FPGA下降沿改变数据。
- // FPGA内部在上升沿采样FLASH发出的数据。
- // 内部输入输出
- wire SB_cs ;// input 高脉冲
- wire SB_wr ;// input
- wire[7:0] SB_wdata ;// input
- wire[7:0] SB_rdata ;// output
- wire SB_wrvld ;// output
-
-
-
- reg [7:0] SB_wdata_int ;// 锁存
- reg [7:0] SB_rdata_int ;// 锁存
- reg [3:0] SB_cnt_bit ;// 关键的计数器,bit计数器 后面全依赖此计数器
- reg [7:0] SB_cnt_div ;// 关键的计数器,分频计数器 后面全依赖此计数器
- wire SB_cnt_bit_up ;// 用于更新SB_cnt_bit
-
- assign SB_cs = ST_cs ;
- assign SB_wr = ST_wr ;
- assign SB_wdata = ST_wdata ;
- assign ST_wrvld = SB_wrvld ;
- assign ST_rdata = SB_rdata ;
-
- assign SB_cnt_bit_up = (SB_cnt_div==div_max);
- assign SB_rdata_up = (SB_cnt_div==div_max/2);
- assign SB_wrvld = (SB_cnt_div==div_max/2) && (SB_cnt_bit==4'ha);
- // SB_wdata_int
- always @(posedge clk or posedge rst)begin
- if(rst)
- SB_wdata_int <=#1 8'b0;
- else if(SB_cs)
- SB_wdata_int <=#1 SB_wdata;
- else if(SB_cnt_bit==4'b1)
- SB_wdata_int <=#1 SB_wdata_int;
- else if(SB_cnt_bit_up)
- SB_wdata_int <=#1 {SB_wdata_int[6:0],1'b0};//MSB
- end
- // reg[3:0] SB_cnt_bit;// 关键的计数器,后面全依赖此计数器
- always @(posedge clk or posedge rst)begin
- if(rst)
- SB_cnt_bit <=#1 4'b0;
- else if(SB_cs==1'b1)
- SB_cnt_bit <=#1 4'b1;
- else if(SB_cnt_bit==4'b0)
- SB_cnt_bit <=#1 4'b0;
- else if(SB_cnt_bit==4'ha && SB_cnt_bit_up)
- SB_cnt_bit <=#1 4'b0;
- else if(SB_cnt_bit_up)
- SB_cnt_bit <=#1 SB_cnt_bit+1'b1;
- end
- // reg [7:0] SB_cnt_div;// 关键的计数器,分频计数器 后面全依赖此计数器
- always @(posedge clk or posedge rst)begin
- if(rst)
- SB_cnt_div <=#1 8'h0;
- else if(SB_cs==1'b1)
- SB_cnt_div <=#1 8'b1;
- else if(SB_cnt_bit_up)
- SB_cnt_div <=#1 8'b0;
- else if( (SB_cnt_bit<=4'd10) && (SB_cnt_bit!=4'd0) )
- SB_cnt_div <=#1 SB_cnt_div+1'b1;
- else
- SB_cnt_div <=#1 8'b0;
- end
- // spi_clk_int
- always @(posedge clk or posedge rst)begin
- if(rst)
- spi_clk_int <=#1 1'b0;
- else if( (SB_cnt_bit==4'b1) ||(SB_cnt_bit==4'ha) )
- spi_clk_int <=#1 1'b0;
- else if( (SB_cnt_div==(div_max/2)) | (SB_cnt_div==div_max) )
- spi_clk_int <=#1 ~spi_clk_int;
- end
- // SB_rdata_int
- always @(posedge clk or posedge rst)begin
- if(rst)
- SB_rdata_int <=#1 8'b0;
- else if(SB_rdata_up)
- SB_rdata_int <=#1 {SB_rdata_int[6:0],spi_din_int};//MSB
- end
-
- assign spi_dout_int = SB_wdata_int[7] ;
- assign SB_rdata = SB_rdata_int ;
-
- assign spi_clk = spi_clk_int ;
- assign spi_csn = spi_csn_int ;
- assign spi_din_int = spi_din ;
- assign spi_dout = spi_dout_int ;
-
- endmodule

- `timescale 1ns/100ps
- module tb ( );
-
- reg clk =0,rst =1;
- always clk =#5 ~clk;
- reg m_cs = 0 ;
- reg m_wr = 0 ;
- reg [2:0] m_addr = 0 ;
- reg [7:0] m_din = 0 ;
- wire [7:0] m_dout ;
-
- wire spi_clk ;
- wire spi_csn ;
- wire spi_din ;
- wire spi_dout ;
-
-
- parameter NOP = 8'hff;
- parameter WREN = 8'h06;//md0
- parameter WRDI = 8'h04;//md0
- parameter RDSR = 8'h05;//md6
- parameter WRSR = 8'h01;//md6
- parameter RDCMD = 8'h03;//md7
- parameter F_RD = 8'h0B;//md8
- parameter PP = 8'h02;//md4
- parameter SE = 8'hD8;//md9
- parameter BE = 8'hC7;//md0
- parameter DP = 8'hB9;//md0
- parameter RES = 8'hAB;//md0
- parameter RDID = 8'h9F;//md6
- //-------------产生spi_din------------
- reg [23:0] rand1=0;
- initial begin
- while(1) begin
- @(negedge spi_clk);
- rand1 = {$random} % 100;
- end
- end
- assign spi_din = rand1[0];
- reg[7:0] rdata_sim;
- reg [7:0] WaitData=8'h80;
- reg [31:0] index ;
- integer i;
-
- initial begin
- rst =1;
- #100;
- @(posedge clk);#1;
- rst =0;
- #100;
- @(posedge clk);#1;
-
- m_interfasc(1,3'h0,8'haa,rdata_sim);//数据aa
- m_interfasc(1,3'h2,8'h01,rdata_sim);//addh
- m_interfasc(1,3'h3,8'h02,rdata_sim);//addm
- m_interfasc(1,3'h4,8'h03,rdata_sim);//addl
- m_interfasc(1,3'h1,PP,rdata_sim);//cmd
- // #600;
- //pp
- for(i=0;i<7;i=1+i) begin
- index = 1;
- while(index)
- begin
- #100;
- @(posedge clk);#1;
- m_interfasc(0,3'h1,8'h00,rdata_sim);//读状态
- if(rdata_sim[3:0]==4'b1011)
- begin
- m_interfasc(1,3'h0,WaitData,rdata_sim);//数据
- index = 0;
- end
- end
- WaitData= WaitData>>1;
- end
- #1000;
- m_interfasc(1,3'h1,NOP,rdata_sim);//cmd
-
-
- #1000;
- // F_RD
- m_interfasc(1,3'h1,F_RD,rdata_sim);//cmd
- for(i=0;i<10;i=1+i) begin
- index = 1;
- while(index)
- begin
- #100;
- @(posedge clk);#1;
- m_interfasc(0,3'h1,8'h00,rdata_sim);//读状态
- if(rdata_sim[3:0]==4'b0111)
- begin
- m_interfasc(0,3'h0,8'h00,rdata_sim);//数据
- index = 0;
- end
- end
-
- end
- #1000;
- m_interfasc(1,3'h1,NOP,rdata_sim);//cmd
- end
- spi_ctrl U_spi_ctrl(
- .clk (clk ),//input clk ,
- .rst (rst ),//input rst ,
- .spi_clk (spi_clk ),//output spi_clk ,
- .spi_csn (spi_csn ),//output spi_csn ,
- .spi_din (spi_din ),//input spi_din ,
- .spi_dout (spi_dout ),//output spi_dout ,
- .m_cs (m_cs ),//output m_cs ,
- .m_wr (m_wr ),//output m_wr ,
- .m_addr (m_addr ),//output m_addr ,
- .m_din (m_din ),//output m_din ,
- .m_dout (m_dout )//output m_dout
- );
- task m_interfasc;//注意分号; 在第一行“task”语句中不能列出端口名称;
- input wr;
- input [3:0] addr;
- input [7:0] wdata;
- output reg[7:0] rdata;
- #100;
- @(posedge tb.clk);#1;
- tb.m_cs = 0 ;
- tb.m_wr = 0 ;
- tb.m_addr = 0 ;
- tb.m_din = 0 ;
- @(posedge tb.clk);#1;
- tb.m_cs = 1 ;
- tb.m_wr = wr ;
- tb.m_addr = addr ;
- tb.m_din = wdata ;
- if(wr==0) begin
- @(posedge tb.clk);#3;
- rdata = tb.m_dout ;
- $display("%h",rdata);
- end else rdata = tb.m_dout ;
- @(posedge tb.clk);#1;
- tb.m_cs = 0 ;
- tb.m_wr = 0 ;
- tb.m_addr = 0 ;
- tb.m_din = 0 ;
- endtask
-
- endmodule

- quit -sim
- cd D:/gaop/SIM/spi_ctrl
- vlib work
- vmap work work
- vlog -novopt -incr -sv -work work "./tb/*.v"
-
- vsim -novopt -t 1ns -L work work.tb
-
- log -r /*
- do wave.do
-
- run 100us
- #
-
-
-

- onerror {resume}
- quietly WaveActivateNextPane {} 0
- add wave -noupdate /tb/U_spi_ctrl/clk
- add wave -noupdate /tb/U_spi_ctrl/rst
- add wave -noupdate /tb/U_spi_ctrl/spi_clk
- add wave -noupdate /tb/U_spi_ctrl/spi_csn
- add wave -noupdate /tb/U_spi_ctrl/spi_din
- add wave -noupdate /tb/U_spi_ctrl/spi_dout
- add wave -noupdate -expand -group m_x /tb/U_spi_ctrl/m_cs
- add wave -noupdate -expand -group m_x /tb/U_spi_ctrl/m_wr
- add wave -noupdate -expand -group m_x /tb/U_spi_ctrl/m_addr
- add wave -noupdate -expand -group m_x /tb/U_spi_ctrl/m_din
- add wave -noupdate -expand -group m_x /tb/U_spi_ctrl/m_dout
- add wave -noupdate -expand -group ST_x /tb/U_spi_ctrl/ST_cs
- add wave -noupdate -expand -group ST_x /tb/U_spi_ctrl/ST_wr
- add wave -noupdate -expand -group ST_x /tb/U_spi_ctrl/ST_wdata
- add wave -noupdate -expand -group ST_x /tb/U_spi_ctrl/ST_wrvld
- add wave -noupdate -expand -group ST_x /tb/U_spi_ctrl/ST_rdata
- add wave -noupdate /tb/U_spi_ctrl/tx_data0
- add wave -noupdate /tb/U_spi_ctrl/rx_data0
- add wave -noupdate /tb/U_spi_ctrl/cmd
- add wave -noupdate /tb/U_spi_ctrl/add_h
- add wave -noupdate /tb/U_spi_ctrl/add_m
- add wave -noupdate /tb/U_spi_ctrl/add_l
- add wave -noupdate -radix ascii /tb/U_spi_ctrl/cur_state
- add wave -noupdate /tb/U_spi_ctrl/ST_change
- add wave -noupdate /tb/rdata_sim
- add wave -noupdate /tb/U_spi_ctrl/state
- add wave -noupdate /tb/U_spi_ctrl/busy
- add wave -noupdate /tb/U_spi_ctrl/SDEmy
- add wave -noupdate /tb/U_spi_ctrl/RXFull
- add wave -noupdate /tb/U_spi_ctrl/WaitData
- add wave -noupdate /tb/U_spi_ctrl/rd_stata
- TreeUpdate [SetDefaultTree]
- WaveRestoreCursors {{Cursor 1} {4052 ns} 0}
- quietly wave cursor active 1
- configure wave -namecolwidth 176
- configure wave -valuecolwidth 102
- configure wave -justifyvalue left
- configure wave -signalnamewidth 1
- configure wave -snapdistance 10
- configure wave -datasetprefix 0
- configure wave -rowmargin 4
- configure wave -childrowmargin 2
- configure wave -gridoffset 0
- configure wave -gridperiod 1
- configure wave -griddelta 40
- configure wave -timeline 0
- configure wave -timelineunits ps
- update
- WaveRestoreZoom {0 ns} {14036 ns}

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。