【西西学FPGA】Lesson18 SPI 与 FLASH

版权声明:欢迎转载交流 https://blog.csdn.net/u011997919/article/details/79228650

2016年5月8日 罗鹏春  Lesson18
内容提要:
1 Flash Memory
2 .sof文件 和 烧写到Flash的操作的区别
3 flash文件的擦除
4 spi的指令时序
//-----------------------------------------正文-------------------------------------------
1 flash memeory:SPI(Serial Peripheral Interface:串行外设接口);
闪存:
     1 长寿命非易失性(断电情况下仍能保持所存储的数据信息)的存储器,
     2 数据删除不是以单个字节为单位而是以固定的区块为单位
     3 闪存是EEPROM的变种,不同的是,
           EEPROM能在字节水平上进行删除重写而不是整个芯片擦写,
           而闪存的大部分芯片需要块擦除。
     4 NOR型和NAND型
      NOR型闪存更像内存,有独立的地址线和数据线,但是价格比较贵,容量比较小;
      NAND型更像硬盘,地址线和数据线是共用的IO,类似硬盘的所有信息都是通过一条硬盘线传送。
      MAND比NOR成本低,容量大。
      NOR闪存适合频繁随机读写的场合,通常用于存储程序代码并直接在闪存内运行。
2   SOF是JTAG模式的下载,速度比较快,但是是掉电失效的。
    POF是ASP模式,是固化在芯片里的,速度比较慢,但是是不会失效的。
   一般在设计调试程序的时候用SOF烧写,应用的时候用POF烧写。
3 flash擦除  【参见相关指令手册】
4 SPI:
 (1)SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
  (2)SPI接口是在CPU和外围低速器件之间进行同步串行数据传输,在主器件的移位脉冲下,数据按位传输,高位在前,地位在后,为全双工通信,数据传输速度总体来说比I2C总线要快,速度可达到几Mbps。
 (3)SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号:

(1)sdi – 主器件(fpag)数据输出,从器件(flash)数据输入
(2)sdo – 主器件数据输入,从器件数据输出
(3)sck – 时钟信号,由主器件产生
(4)cs_n  – 从器件使能信号,由主器件控制


//=====================================

【西西学FPGA】Lesson19

2016年5月8日 罗鹏春
发送指令 完成flasg 的PP操作
//----------------------------------------------------正文
module flash_pp(
        input wire sclk,
        input wire s_rst_n,
        input wire key_in,
        input wire sdo,
        
        output reg cs_n,
        output reg sdi,
        output reg sck,
        output reg [7:0] data_out,
        output reg data_flag

);
        parameter//for state
                IDLE = 4'd0,
                SE_WREN = 4'd1,//擦除操作的写使能信号
                SE_DELAY = 4'd2,//1024个时钟
                SE_OP = 4'd3,//擦除操作
                PP_WAIT = 4'd4,//等待pp操作的key输入
                PP_WREN = 4'd5,//pp操作的写使能信号
                PP_DELAY = 4'd6,//1024个时钟
                PP_OP = 4'd7,//pp操作
                RD_WAIT = 4'd8,//等待读信号
                RD_OP = 4'd9;//read操作
        parameter//for introduction
                WREN = 8'b0000_0110,
                READ = 8'b0000_0011,
                PP = 8'b0000_0010,
                SE = 8'b1101_1000,
                ADDR = 24'h00_0000,
                DATA_INIT = 8'b0000_0000;//发送的初始数据
                        
                
        reg pp_flag;
        reg [4:0] cnt_32;//CS有效的时候,进行满32清零的计数操作
        reg [9:0] cnt_pp;//记录cnt_32满的个数,pp的最大计数为260-1;
        reg [3:0] state;
        
        reg [1:0] cnt_4;
        reg [7:0] send_data;//发送的数据给spi
        reg [7:0] data;//数值的计算问题
        reg [7:0] data_out_tmp;
        reg data_flag_delay;
        
//------------------------------------输出端口---------------------
//cs_n,
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cs_n <= 1'b1;
        else
                begin
                case(state)
                        IDLE :
                                if(key_in == 1'b1)
                                        cs_n <= 1'b0;
                        SE_WREN :
                                       if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                               cs_n <= 1'b1;
                        SE_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b0;
                        SE_OP :
                                if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b1;
                        PP_WAIT:
                                if(key_in == 1'b1)
                                        cs_n <= 1'b0;
                        PP_WREN:
                                if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b1;
                        PP_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b0;
                        PP_OP:
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b1;
                        RD_WAIT :
                                if(key_in == 1'b1)
                                        cs_n <= 1'b0;
                        RD_OP :
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        cs_n <= 1'b1;
                        default:
                                cs_n <= 1'b1;
                        endcase
                end
//sdi, 
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                sdi <= 1'b0;
        else if ((cnt_4 == 2'd0)&&(cs_n == 1'b0))
                sdi <= send_data[7];
        
//sck    
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                sck  <= 1'b0;
        else if (pp_flag != 1'b1)
                sck  <= 1'b0;
        else if (pp_flag == 1'b1)
                begin
                        if(cnt_4 == 2'd0)
                                sck <= 1'b0;
                        else if(cnt_4 == 2'd2)
                                sck <= 1'b1;
                end
        else
                sck  <= 1'b0;      
//data_out,
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_out <= 8'b0;
        else if(data_flag_delay == 1'b1)
                data_out <= data_out_tmp;
//data_flag
////reg data_flag_delay;
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_flag_delay <= 1'b0;
        else if((state == RD_OP)&&(cnt_pp >= 10'd5)&&(cnt_pp <= 260)&&(cnt_32 == 5'd30))
                data_flag_delay <= 1'b1;
        else
                data_flag_delay <= 1'b0;
                
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_flag <= 1'b0;
        else if (data_flag_delay == 1'b1)
                data_flag <= 1'b1;
        else
                data_flag <= 1'b0;
                
//reg [7:0] data_out_tmp;
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_out_tmp <= 8'b0;
        else if((state == RD_OP)&&(cnt_pp >= 10'd4)&&(cnt_pp <= 260))
                begin
                        case(cnt_32)
                        5'd2: data_out_tmp[7] <= sdo;
                        5'd6:   data_out_tmp[6] <= sdo;
                        5'd10:   data_out_tmp[5]<= sdo;
                        5'd14:  data_out_tmp[4] <= sdo;
                              
                        5'd18:  data_out_tmp[3] <= sdo;
                        5'd22:  data_out_tmp[2] <= sdo;
                        5'd26:  data_out_tmp[1] <= sdo;
                        5'd30:  data_out_tmp[0] <= sdo;
                        
                        default:
                                data_out_tmp <= data_out_tmp;
                        endcase
                end
                
//----------------------------发送数据-------------------------------
//reg [7:0] send_data;//发送的数据给sdi
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                send_data <= DATA_INIT;
        else if (cnt_4 == 2'd2)
                send_data <= {send_data[6:0],send_data[7]};
        else
                begin
                        case(state)
                        SE_WREN :
                                       if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
                                               send_data <= WREN;
                        SE_OP :
                                if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
                                        send_data <= SE;
                                else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
                                        send_data <= ADDR[23:16];
                                else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[15:8];
                                else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[7:0];
                
                        PP_WREN:
                                if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
                                               send_data <= WREN;
                        PP_OP:
                                if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
                                        send_data <= PP;
                                else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[23:16];
                                else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[15:8];
                                else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[7:0];
                                else if(cnt_32 == 5'd31)
                                        send_data <= data;

                        RD_OP :
                                if((cnt_pp == 10'd0)&&(cnt_32 == 5'd31))
                                        send_data <= READ;
                                else if((cnt_pp == 10'd1)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[23:16];
                                else if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[15:8];
                                else if((cnt_pp == 10'd3)&&(cnt_32 == 5'd31))
                                        send_data  <= ADDR[7:0];
                                        
                        default:
                                send_data <= DATA_INIT;
                endcase
        end
                
//reg [7:0] data;//数值的计算问题 
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data <= DATA_INIT;
        else if ((state == PP_OP)&&(cnt_pp >= 10'd4)&&(cnt_pp <= 259)&&(cnt_32 == 5'd31)&&(cnt_4 == 2'd3))
                data <=  data + 1'b1;
        
  
// ---------------------------------中间变量-------------------------      
//pp_flag;//在操作中的标志
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                pp_flag <= 1'b0;
        else if (key_in == 1)
                pp_flag <= 1'b1;
        else if(((state ==RD_OP)&&(cnt_pp == 10'd261)&&(cnt_32 == 5'd31))||(state ==PP_WAIT)||(state ==RD_WAIT))
                pp_flag <= 1'b0;
        

//cnt_32;/
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cnt_32 <= 5'd0;
        else if(cnt_32 == 5'd31)
                cnt_32 <= 5'd0;
        else if(pp_flag == 1'b1)
                cnt_32 <= cnt_32 + 1'b1;
        else
                cnt_32 <= 5'd0;
                
//cnt_pp;/
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cnt_pp <= 10'd0;
        else
                begin
                        case(state)
                        IDLE :
                                if(key_in == 1'b1)
                                        cnt_pp <= 10'd0;
                                        
                        SE_WREN :
                                       if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                               cnt_pp <= 10'd0;
                                       else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        SE_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                                        
                        SE_OP :
                                if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        PP_WAIT:
                                if(key_in == 1'b1)
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        PP_WREN:
                                if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        PP_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        PP_OP:
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        RD_WAIT :
                                if(key_in == 1'b1)
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                                        
                        RD_OP :
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        cnt_pp <= 10'd0;
                                else if (cnt_32 == 5'd31)
                                        cnt_pp <= cnt_pp + 1'b1;
                        default:
                                cnt_pp <= 10'd0;
                endcase
        end
                
                                
        
//state;
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                state <= IDLE;
        else
        begin
                case(state)
                        IDLE :
                                if(key_in == 1'b1)
                                        state <= SE_WREN;
                        SE_WREN :
                                       if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                               state <= SE_DELAY;
                        SE_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        state <=SE_OP;
                        SE_OP :
                                if((cnt_pp == 10'd5)&&(cnt_32 == 5'd31))
                                        state <= PP_WAIT ;
                        PP_WAIT:
                                if(key_in == 1'b1)
                                        state <= PP_WREN;
                        PP_WREN:
                                if((cnt_pp == 10'd2)&&(cnt_32 == 5'd31))
                                        state <= PP_DELAY;
                        PP_DELAY:
                                if((cnt_pp == 10'd31)&&(cnt_32 == 5'd31))
                                        state <= PP_OP;
                        PP_OP:
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        state <= RD_WAIT;
                        RD_WAIT :
                                if(key_in == 1'b1)
                                        state <= RD_OP ;
                        RD_OP :
                                if((cnt_pp == 10'd261)&&(cnt_32 == 5'd31))
                                        state <= IDLE;
                        default:
                                state <= IDLE;  
                        endcase
                end

//       
//cnt_4; 
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cnt_4 <= 2'd0;
        else
                begin
                        case(state)
                        SE_WREN :
                                       if(cnt_pp == 10'd1)
                                               begin
                                                       if(cnt_4 == 2'd3)
                                                               cnt_4 <= 2'd0;
                                                       else
                                                               cnt_4 <= cnt_4 + 1'b1;
                                               end
                                       else
                                               cnt_4 <= 2'd0;
                                                               
                        SE_OP :
                                if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd4))
                                        begin
                                                       if(cnt_4 == 2'd3)
                                                               cnt_4 <= 2'd0;
                                                       else
                                                               cnt_4 <= cnt_4 + 1'b1;
                                               end
                                       else
                                               cnt_4 <= 2'd0;
                                               
                        PP_WREN:
                                if(cnt_pp == 10'd1)
                                        begin
                                                       if(cnt_4 == 2'd3)
                                                               cnt_4 <= 2'd0;
                                                       else
                                                               cnt_4 <= cnt_4 + 1'b1;
                                               end
                                       else
                                               cnt_4 <= 2'd0;
                                               
                        PP_OP:
                                if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd260))
                                        begin
                                                       if(cnt_4 == 2'd3)
                                                               cnt_4 <= 2'd0;
                                                       else
                                                               cnt_4 <= cnt_4 + 1'b1;
                                               end
                                       else
                                               cnt_4 <= 2'd0;
                        RD_OP :
                                if((cnt_pp >= 10'd1)&&(cnt_pp <= 10'd260))
                                        begin
                                                       if(cnt_4 == 2'd3)
                                                               cnt_4 <= 2'd0;
                                                       else
                                                               cnt_4 <= cnt_4 + 1'b1;
                                               end
                                       else
                                               cnt_4 <= 2'd0;
                        default:
                                cnt_4 <= 2'd0;
                        endcase
                end
endmodule
//----------------------------------------------RAM_CONTROLLER
module ram_controller(
        input wire sclk,
        input wire s_rst_n,
        input wire [7:0] data_in,
        input wire data_flag,
        input wire key_in,
        
        output wire [7:0] data_to_ram,//to 双口ram
        output reg [7:0] write_addr_to_ram,
        output reg [7:0] read_addr_to_ram,
        output reg wren_to_ram,
        output reg read_data_flag
        );
        reg [25:0] clk_cnt;//1s 寄存器
        reg [1:0] key_in_cnt;
parameter
        CLK_CNT = 26'd2500_0000;
//key_in_cnt
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                key_in_cnt <= 2'd0;
        else if(key_in_cnt == 2'd3)
                key_in_cnt <= key_in_cnt;
        else if  (key_in == 1'b1)
                key_in_cnt <= key_in_cnt + 1'b1;
//clk_cnt
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                clk_cnt <= 26'd0;
        
        else if(clk_cnt == CLK_CNT)
                clk_cnt <= 26'd0;
        else if(write_addr_to_ram == 8'h00)
                clk_cnt <= clk_cnt + 1'b1;

//  data_to_ram,
assign data_to_ram = data_in;
//wren_to_ram
always@(posedge sclk )
        wren_to_ram <=  data_flag;           
//assign wren_to_ram = data_flag; 
//  write_addr_to_ram, 
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                write_addr_to_ram <= 8'd0;
        else if (wren_to_ram == 1'b1)
                write_addr_to_ram <= write_addr_to_ram + 1'b1;
//read_data_flag
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                read_data_flag <= 1'b0;
        else if((read_addr_to_ram >= 8'd0)&&(read_addr_to_ram <= 8'd255)&&(clk_cnt == 26'd0))
                read_data_flag <= 1'b1;
        else
                read_data_flag <= 1'b0;
                
//read_addr_to_ram, 
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                read_addr_to_ram <= 8'b0;
        else if ((clk_cnt == CLK_CNT)&&(read_addr_to_ram == 8'd255)&&(key_in_cnt == 2'd3))
                read_addr_to_ram <= 8'b0;
        else if ((clk_cnt == CLK_CNT)&&(key_in_cnt == 2'd3))
                read_addr_to_ram <= read_addr_to_ram + 1'b1;
                
endmodule
//----------------------------------------------top
module flash_controller(
        input wire sclk,
        input wire s_rst_n,
        input wire key_in,

// input wire sdo,//from flash
        
        output wire [2:0] sel,//to seg
        output wire [7:0] seg

        
);
        wire sdo;
        wire key_out;
        wire sck;
        wire sdi;
        wire cs_n;
        wire [7:0] data_out;
        wire data_flag;
        
        wire [7:0] data_to_ram;//to 双口ram
        wire [7:0] write_addr_to_ram;
        wire [7:0] read_addr_to_ram;
        wire wren_to_ram;
        wire [7:0] q_sig;
        wire read_data_flag;
        
        wire [23:0] bcd_out;
        wire out_flag;
        
key_in key_in_inst(
        .sclk (sclk ),
        .s_rst_n (s_rst_n ),
        .key_in (key_in ),
                                        
        .flag        (key_out        )
        );
        
flash_pp flash_pp_inst(
        .sclk (sclk ),
        .s_rst_n (s_rst_n ),
        .key_in (key_out ),
        .sdo (sdo ),
                                 
        .cs_n (cs_n ),
        .sdi (sdi ),
        .sck    (sck    ),
        .data_out (data_out),
        .data_flag (data_flag)
        );
        
        
flash   flash_inst (
    .asdo_in ( sdi ),
    .asmi_access_granted ( 1'b1 ),
    .dclk_in ( sck ),
    .ncso_in ( cs_n ),
    .noe_in ( 1'b0 ),
    .asmi_access_request (   ),
    .data0_out ( sdo  )
    );
    
//data_out /data_flag -> ram
ram_controller ram_controller_inst(
        .sclk (sclk ),  
        .s_rst_n (s_rst_n ),  
        .data_in (data_out), 
        .data_flag (data_flag) ,
        .key_in (key_out ),
        
        .data_to_ram (data_to_ram ),//to 双口ram
        .write_addr_to_ram (write_addr_to_ram ),
        .read_addr_to_ram (read_addr_to_ram ),
        .wren_to_ram            (wren_to_ram            ),
        .read_data_flag (read_data_flag)
        );
ram8x256 ram8x256_inst (
        .clock (sclk ),
        .data ( data_to_ram ),
        .rdaddress ( read_addr_to_ram ),
        .wraddress ( write_addr_to_ram ),
        .wren ( wren_to_ram ),
        .q ( q_sig )
        );
//bin_bcd bin_bcd_inst(
// .sclk (sclk ),  
// .s_rst_n (s_rst_n ),  
// .bin_in ({16'b0,q_sig} ),
// .in_flag (read_data_flag ),
//
// .bcd_out(bcd_out),
// .out_flag(out_flag)
// );
seg seg_inst(
        .sclk (sclk ),   
        .s_rst_n (s_rst_n ),   
        .num (q_sig),
        .enable (read_data_flag),
        
        .sel(sel),
        .seg(seg)
        );

endmodule



//================================

【西西学FPGA】Lesson20uart+controller+spi
/*------------------------------------------------------------
模块名:command
功能描述:

时间:2016.5.18
作者:xizi cheng
联系方式:[email protected]
------------------------------------------------------------*/
module command(
        input wire sclk,
        input wire s_rst_n,
        
        input wire [7:0] Rx_data,//form uart .rx_module
        input wire Rx_flag,//一个系统周期,标志rx_data有效
        
        input wire Tx_end,//from uart.tx_module
        input wire ending_flag,
        
        input wire [7:0] R_flash_data,//from flash_ctrl
        input wire R_flash_flag,//读flash指令,读出的数据以及有效信号
        
        input wire [7:0] W_flash_addr,//写flash指令,将存入输入ram的数据写入flash //fromflash_ctrl
        output wire [7:0] W_flash_data,//比W_flash_addr晚一个周期
        
        output reg [7:0] Tx_data,//to uart.tx_module
        output reg Tx_flag,
        
        output reg W_request,//to  flash_ctrl
        output reg R_request,//
        output reg E_request,//
        output reg [23:0] Flash_start_addr//
        
        ); 
 
        parameter
                IDLE = 4'd0,
                WAIT_FOR_55 = 4'd1,
                WAIT_FOR_D5     = 4'd2,
                WAIT_FOR_FA     = 4'd3,
                WAIT_FOR_ADDR   = 4'd4,                 
                WAIT_FOR_OP     = 4'd5,
                READ_00_00      = 4'd6,
                READ_00_01      = 4'd7,
                WRITE_00_00     = 4'd8,
                WRITE_00_01     = 4'd9,                    
                ERASE_00_00     = 4'd10,
                ERASE_00_01     = 4'd11,
                READ_OP = 4'd12,
                WRITE_OP = 4'd13,
                ERASE_OP = 4'd14,
                WRITE_END = 4'd15,
                
                WRITE_NUM_CNT = 8'd255;
                
        reg [7:0] data_to_inram           ;
// reg [7:0] read_addr_to_inram ;
        reg [7:0] write_addr_to_inram ;
        reg wren_to_inram ;
        wire [7:0] q_from_inram ;
        
        reg [7:0] data_to_outram          ;
        reg [7:0] read_addr_to_outram ;
        reg [7:0] write_addr_to_outram ;
        reg wren_to_outram ;
        wire [7:0] q_from_outram ;
        
        reg send_end;
        
        reg [3:0] state;
        reg [2:0] cnt_for_55;
        reg [1:0] cnt_for_addr;
// reg [7:0] write_cnt;
        reg [7:0] send_cnt;
        reg send_flag;
        reg tx_flag_delay2;
        
        reg write_flag;
//------------------------------------------------------输出端口              
//W_request,
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                W_request <= 1'b0;
        else if (write_addr_to_inram == 8'd255 &&(wren_to_inram == 1'b1) &&(state == WRITE_OP))
                W_request <= 1'b1;
        else
                W_request <= 1'b0;
    
//R_request,
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                R_request <= 1'b0;
        else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00)&&(state == READ_00_01))
                R_request <= 1'b1;
        else
                R_request <= 1'b0;
//E_request,    
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                E_request <= 1'b0;
        else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00)&&(state == ERASE_00_01))
                E_request <= 1'b1;
        else
                E_request <= 1'b0;
//------------------------------------------------------中间变量
//cnt_for_addr
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cnt_for_addr <= 2'd0;
        else if((cnt_for_addr == 2'd2)&&(Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
                cnt_for_addr <= 2'd0;
        else if ((Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
                cnt_for_addr <= cnt_for_addr + 1'b1;
                
//cnt_for_55;
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                cnt_for_55 <= 3'd0;
        else if((state != WAIT_FOR_55))
                cnt_for_55 <= 3'd0;
        else if (cnt_for_55 == 3'd7)
                cnt_for_55 <= 3'd0;
        else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h55)&&(state == WAIT_FOR_55))
                cnt_for_55 <= cnt_for_55 + 1'b1;
        
                
//Flash_start_addr
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                Flash_start_addr <= 24'd0;
        else if ((Rx_flag == 1'b1)&&(state == WAIT_FOR_ADDR))
                begin
                        case(cnt_for_addr)
                                2'd0:
                                        Flash_start_addr[7:0] <= Rx_data;
                                2'd1:
                                        Flash_start_addr[15:8] <= Rx_data;
                                2'd2:
                                        Flash_start_addr[23:16] <= Rx_data;
                                        
                                default:
                                        Flash_start_addr <= 24'd0;
                        endcase
                end
        
//----------------------------------------state;   
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                 state <= IDLE;
        else
                begin
                case(state)
                        IDLE :
                                if((Rx_data == 8'h55)&&(Rx_flag == 1'b1))
                                        state <= WAIT_FOR_55;
                        WAIT_FOR_55 :
                                if((cnt_for_55 == 3'd5)&&(Rx_data == 8'h55)&&(Rx_flag == 1'b1))
                                        state <= WAIT_FOR_D5;
                                else if((Rx_data != 8'h55)&&(Rx_flag == 1'b1))
                                        state <= IDLE;
                        WAIT_FOR_D5     :
                                if((Rx_data == 8'hD5)&&(Rx_flag == 1'b1))
                                        state <= WAIT_FOR_FA  ;
                                else if((Rx_data != 8'hD5)&&(Rx_flag == 1'b1))
                                        state <= IDLE;
                        WAIT_FOR_FA     :
                                if((Rx_data == 8'hFA )&&(Rx_flag == 1'b1))
                                        state <= WAIT_FOR_ADDR ;
                                else if((Rx_data != 8'hFA)&&(Rx_flag == 1'b1))
                                        state <= IDLE;
                                        
                        WAIT_FOR_ADDR   :
                                if((cnt_for_addr == 2'd2)&&(Rx_flag == 1'b1))
                                        state <= WAIT_FOR_OP;
                                        
                        WAIT_FOR_OP     :
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h55))
                                        state <= READ_00_00;
                                else if((Rx_flag == 1'b1)&&(Rx_data == 8'hAA))
                                        state <= WRITE_00_00;
                                else if((Rx_flag == 1'b1)&&(Rx_data == 8'hF0))
                                        state <= ERASE_00_00;//输入数据为擦除
                                else if(Rx_flag == 1'b1)
                                        state <= IDLE;
                                                
                        READ_00_00      :
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= READ_00_01 ;
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;
                                
                        READ_00_01      : //保留位必须为00
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= READ_OP ;                  
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;                        

                                //------------------------------
                        WRITE_00_00     :
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= WRITE_00_01 ;
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;
                        WRITE_00_01     :
                                      if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= WRITE_OP ;                  
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;                        
     
                        ERASE_00_00     :
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= ERASE_00_01;
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;
                        ERASE_00_01     :
                                if((Rx_flag == 1'b1)&&(Rx_data == 8'h00))
                                        state <= ERASE_OP ;                  
                                else if ((Rx_flag == 1'b1)&&(Rx_data != 8'h00))
                                        state <= IDLE;
                                           
                        READ_OP :
                                 if ( send_end == 1'b1)
                                         state <= IDLE;
               
                        WRITE_OP : 
                                if(W_request == 1'b1)
                                        state <= WRITE_END;
                        ERASE_OP :
                                if(send_cnt == 8'd15 && Tx_end == 1'b1)
                                        state <= IDLE;
                        WRITE_END:
                                if(send_cnt == 8'd15 && Tx_end == 1'b1)
                                        state <= IDLE;
                        default:
                                state <= IDLE;  
                endcase
                end
//---------------------------------------------------------write to inram
//write_flag
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n) 
                write_flag <= 1'b0;
        else if (write_addr_to_inram ==8'd255 && wren_to_inram == 1'b1)
                write_flag <= 1'b0;
        else if ((Rx_flag == 1'b1)&&(Rx_data == 8'h00) &&(state == WRITE_00_01))
                write_flag <= 1'b1;   
//data_to_inram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_to_inram <=8'd0;
        else if (state != WRITE_OP)
                data_to_inram <=8'd0;
        else if ((state == WRITE_OP)&&(Rx_flag == 1'b1))
                data_to_inram <= Rx_data;
       
                 
//write_addr_to_inram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                write_addr_to_inram <= 8'd0;
        else if (state != WRITE_OP)
                write_addr_to_inram <= 8'd0;
        else if (write_addr_to_inram == 8'd255 && wren_to_inram == 1'b1)
                write_addr_to_inram <= 8'd0;
        else if ((state == WRITE_OP)&&(wren_to_inram  == 1'b1))
                write_addr_to_inram <= write_addr_to_inram + 1'b1;
                
//wren_to_inram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                wren_to_inram <=1'b0;
        else if ((state == WRITE_OP)&&(Rx_flag == 1'b1)&&(write_addr_to_inram <= 8'd255)&&(write_flag == 1'b1))
                wren_to_inram <=1'b1;
        else
                wren_to_inram <=1'b0;
                        
ram_8x256 in_ram_8x256 (
        .clock ( sclk ),
        .data ( data_to_inram ),//
        
        .rdaddress ( W_flash_addr ),//
        .wraddress ( write_addr_to_inram ),//
        .wren ( wren_to_inram ),//
        
        .q ( W_flash_data )//
        );
        
         
//---------------------------------------------------------write to outram
//Tx_data q_from_outram
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                Tx_data <= 8'hFF;
        else if (ending_flag== 1&&(state == ERASE_OP ||state == READ_OP ||state == WRITE_END))
                Tx_data <= 8'h55;
        else if (send_flag == 1)
                Tx_data <= q_from_outram;
        else if(send_flag == 0 &&(state == ERASE_OP ||state == READ_OP ||state == WRITE_END))
                begin
                        case(send_cnt)
                                
                                8'd1:if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd2:if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd3:if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd4:if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd5:if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd6: if(Tx_end == 1)
                                        Tx_data <= 8'h55;
                                8'd7: if(Tx_end == 1)                                
                                        Tx_data <= 8'hd5;                              
                                8'd8: if(Tx_end == 1)                                 
                                        Tx_data <=8'hFC;                                
                                8'd9: if(Tx_end == 1)                                
                                             Tx_data <=Flash_start_addr[7:0];                                                                 
                                8'd10: if(Tx_end == 1)                                 
                                        Tx_data <=Flash_start_addr[15:8];               
                                8'd11: if(Tx_end == 1)                                
                                        Tx_data <=Flash_start_addr[23:16];              
                                8'd12: if(Tx_end == 1)                                
                                        Tx_data <= 8'h99;                               
                                8'd13: if(Tx_end == 1)                                
                                        Tx_data <= 8'h00;                               
                                8'd14: if((Tx_end == 1)&&(state == ERASE_OP ))        
                                        Tx_data <= 8'hf0;                               
                                        else if ((Tx_end == 1)&&(state == READ_OP))    
                                        Tx_data <= 8'h55;                               
                                        else if ((Tx_end == 1)&&(state == WRITE_END))   
                                        Tx_data <= 8'hAA;                               
                                        
                                        
                        endcase
                end
 //send_flag
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                send_flag <= 1'b0;
        else if (send_end == 1'b1)
                send_flag <= 1'b0;
        else if ( state == READ_OP &&send_cnt == 8'd15&& Tx_end == 1'b1)
                send_flag <= 1'b1;
                                
//tx_flag_delay2
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                tx_flag_delay2<= 1'b0;
        else
                tx_flag_delay2<= Tx_end;
        
//Tx_flag
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                Tx_flag <= 1'b0;
        else if(send_flag == 1)
                Tx_flag <= tx_flag_delay2;
        else if(send_flag == 0)
                begin
                if(((state == ERASE_OP||state == WRITE_END)&&(send_cnt == 8'h0F))||(state == READ_OP)&&(send_cnt == 8'hFF))
                        Tx_flag <= 1'b0;
                else if ((state == ERASE_OP||state == WRITE_END)||(state == READ_OP)&&(send_cnt != 8'h0f))
                        Tx_flag <= Tx_end||ending_flag;
                else
                        Tx_flag <= 1'b0;
                end
        else
                Tx_flag <= 1'b0;
                                
 //read_addr_to_outram
 always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                read_addr_to_outram <= 8'd0;
        else if (read_addr_to_outram == 8'd255 && tx_flag_delay2 == 1 && send_flag == 1'b0)
                read_addr_to_outram <= 8'd0;
        else if (send_flag == 1 && Tx_flag == 1 && state == READ_OP)
                read_addr_to_outram <= read_addr_to_outram + 1'b1;

//reg [7:0] send_cnt
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                send_cnt <= 8'd0;
        else if (state == IDLE)
                send_cnt <= 8'd0;
        else if (send_end == 1'b1)
                send_cnt <= 8'd0;
        else if (send_flag == 1'b0 &&(state == READ_OP||state ==WRITE_END||state == ERASE_OP) &&send_cnt == 8'd15 && Tx_end == 1)
                send_cnt <= 8'd0;
        else if ((state == READ_OP||state == WRITE_END||state == ERASE_OP)&&(send_cnt < 255) &&(ending_flag == 1 || Tx_end == 1))
                send_cnt <= send_cnt + 1'b1;
//send_end
always @(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                send_end <= 1'b0;
        else if ( state == READ_OP &&send_cnt == 8'd255 && send_flag == 1 && Tx_flag == 1)
                send_end <= 1'b1;
        else
                send_end <= 1'b0;
                

//data_to_outram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                data_to_outram <=8'd0;
        else if (state != READ_OP)
                data_to_outram <=8'd0;
        else if ((state == READ_OP)&&(R_flash_flag == 1'b1))
                data_to_outram <=R_flash_data;
       
                        
//write_addr_to_outram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                write_addr_to_outram <= 8'd0;
        else if (write_addr_to_outram == WRITE_NUM_CNT && wren_to_outram == 1'b1 )
                write_addr_to_outram <= 8'd0;
        else if ((state == READ_OP)&&(wren_to_outram  == 1'b1))
                write_addr_to_outram <= write_addr_to_outram + 1'b1;
                
//wren_to_outram
always@(posedge sclk or negedge s_rst_n)
        if(!s_rst_n)
                wren_to_outram <=1'b0;
        else if ((state == READ_OP)&&(R_flash_flag == 1'b1))
                wren_to_outram <=1'b1;
        else
                wren_to_outram <=1'b0;
                
ram_8x256 out_ram_8x256 (
        .clock ( sclk ),
        .data ( data_to_outram ),//
        
        .rdaddress ( read_addr_to_outram ),//
        
        .wraddress ( write_addr_to_outram ),//
        .wren ( wren_to_outram ),//
        .q ( q_from_outram  )//
        );


endmodule

//=============Lesson21

时间 2016.5.21
1 .do文件
2 写端口
3 写跳转状态
4 写文档(2,3,4,是一件事情)
5 信号波形图(visio)
6 总体架构图

//修改过后的Tx_module,Tx_end 产生的条件和方法
//-----------------------------尤老师的tx模块
module rs232_phy_tx(
        input wire sclk,
        input wire rst_n,
        //interface for rs232 rx
        output reg tx_d,
        //interface for internal logic
        input wire [7:0] tx_data,
        input wire tx_data_sync,
        output wire busy
);

reg [9:0] tx_data_t;
reg cnt_en;
reg end_flag;
reg div_end_flag;
reg [13:0] div_cnt;
reg [3:0] baud_cnt;
reg shift_flag;

parameter BAUD_RATE =1085-1; //125M/baud_rate(115200bps)=1085;
                                                //9600bps=13021;14400bps=8680;19200bps=6510;38400bps=3255;
                                                //57600bps=2170;115200bps=1085;230400bps=542;460800bps=271;
parameter INVERT =0; //如果invert=0下降沿"0"为起始位,第10位停止位为高。invert=1则相反。

parameter FREQ_ERROR =400; //收发端的频率误差

always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)begin
                tx_data_t<=10'h3ff;
        end
        else if(tx_data_sync=='d1)
                tx_data_t<={1'b1,tx_data,1'b0};
        else if(shift_flag=='d1)
                tx_data_t<={1'b1,tx_data_t[9:1]};

always @(posedge sclk or negedge rst_n)
        if(rst_n == 1'b0)
                div_end_flag<='d0;
        else if(div_cnt==(BAUD_RATE - 1))
                div_end_flag<='d1;
        else
                div_end_flag<='d0;

always @(posedge sclk or negedge rst_n)
        if(rst_n == 1'b0)
                end_flag<='d0;
        else if(div_cnt==(BAUD_RATE -FREQ_ERROR) && baud_cnt=='d9)
                end_flag<='d1;
        else
                end_flag<='d0;
        
                
always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)
                cnt_en<='d0;
        else if(end_flag=='d1)
                cnt_en<='d0;
        else if(tx_data_sync)
                cnt_en<='d1;
                
always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)
                div_cnt<='d0;
        else if(cnt_en=='d1 && div_end_flag=='d1)
                div_cnt<='d0;
        else if(cnt_en=='d1)
                div_cnt<=div_cnt+'d1;
        else div_cnt<='d0;
        
always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)
                baud_cnt<='d0;
        else if(cnt_en=='d1 && end_flag=='d1)
                baud_cnt<='d0;
        else if(cnt_en=='d1 && div_end_flag=='d1)
                baud_cnt<=baud_cnt+'d1;
        else if(cnt_en=='d0)
                baud_cnt<='d0;

always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)
                shift_flag<='d0;
        else if(cnt_en=='d1 && div_cnt=='d0 && baud_cnt!='d0)
                shift_flag<='d1;
        else shift_flag<='d0;
        
always @(posedge sclk or negedge rst_n)
        if(rst_n=='d0)begin
                if(INVERT=='d0)
                        tx_d<=1'b1;
                else tx_d<=1'b0;
        end
        else if(INVERT=='d0)
                tx_d<=tx_data_t[0];
        else
                tx_d<=~tx_data_t[0];

assign busy=cnt_en;
endmodule

//------------------------------------------------------------tx_end 产生条件

module uart(
        input wire sclk ,
        input wire s_rst_n ,
        input wire rx ,
         
        input wire [7:0] tx_data ,
        input wire tx_flag ,
        
        output wire [7:0] rx_data ,
        output wire rx_flag ,
        
        output wire tx ,
        output reg tx_end
        );
        
        
//tx_module tx_module_inst(
// .sclk (sclk ),
// .s_rst_n (s_rst_n ),
// .pi_flag (tx_flag ),
// .pi_num (tx_data ),
//
// .po_tx          (tx          ),
// .tx_end (tx_end )
// );
defparam rs232_phy_tx.BAUD_RATE=50000000/9600;
rs232_phy_tx rs232_phy_tx(
        .sclk(sclk),
        .rst_n(s_rst_n),
        
        .tx_d(tx),
        
        .tx_data(tx_data),
        .tx_data_sync(tx_flag),
        .busy(busy)
);

reg busy_delay;
always@( posedge sclk )
        
                busy_delay <= busy;
                
always@(posedge sclk )
        if(busy == 1'b0 && busy_delay ==1'b1)
                tx_end <= 1'b1;
        else
                tx_end <= 1'b0;

                
rx_module rx_module_inst(
        .sclk (sclk ),
        .s_rst_n (s_rst_n ),
        .rx_data_in (rx ),
        
        .po_rx_data (rx_data ),
        .po_rx_flag     (rx_flag    )
        );

endmodule

//课后总结:
1 最初觉得在最后一个clk产生tx_end信号也不会影响到自己发送的数据,所以tx_end产生的条件是在最后一个bit产生的时候,baut_cnt == 波特率/2
2 后来因为接收的数据一直不对,因此老师建议我修改tx_end信号的产生条件,于是用老师的模块来生成tx_end;在发送数据的时候有了flag恒为高,当数据完全发送完成的时候,flag拉低,就利用这个flag的下降沿产生一个tx_end信号,当前数据完全发送而之后的信号也能立刻发送。

在电路世界,虽然提高效率也重要,但是数据的准确性还是需要强调。


猜你喜欢

转载自blog.csdn.net/u011997919/article/details/79228650