verilog spi master源码

*爱你&永不变心* 提交于 2020-08-18 05:13:20
module spi_master(sysclk,key,reset,mosi,miso,sclk,ss,led);
  input            sysclk;       
  input            reset;
  input            miso;
  input    [1:0]   key;
  output           mosi;
  output           ss;
  output           sclk;
  output   [1:0]   led;               //   led?????????
 
  
  reg              mosi;
  reg              sclk;
  reg              ss;
  
  reg              en;            //   ????
  reg     [7:0]    shifter;       //   ?????
  reg     [1:0]    cnt;           //   ?????
  reg     [5:0]    cnt1;
  reg     [12:0]   cnt2;
  reg     [6:0]    cnt3;
  reg     [7:0]    data;          //   ??????
  reg     [3:0]    count;         
  reg     [4:0]    addr;
  reg     [1:0]    key_buf1;      //   ???????
  reg     [1:0]    key_buf2;
  reg     [1:0]    key_on_r;
  reg     [1:0]    key_on_rr;
  wire    [1:0]    key_on;        //   ???????????????????
  wire             clk5khz;       
  wire             sclk2;         //   ???sclk?????
  
  always @(posedge sysclk or negedge reset)
   if(~reset)
    cnt2 <= 13'd0;
   else if(cnt2== 13'd6400)
    cnt2 <= 13'd0;
   else
    cnt2 <= cnt2 + 13'd1;
  
  assign clk5khz = (cnt2 == 13'd6400);         //  ????
  
  always @(posedge sysclk or negedge reset)
   if(~reset)
    begin
     key_buf1 <= 2'b11;
     key_buf2 <= 2'b11;
    end
   else if(clk5khz) 
    begin
     key_buf1 <= key;
     key_buf2 <= key_buf1;
    end
    //  ?????????????????????
    wire [1:0] nege_edge=key_buf2 & (~key_buf1);
    
    //  ???????????????????20ms?????????
    always @(posedge sysclk or negedge reset)
     if(~reset)
      cnt3 <= 7'b0;     
     else if(clk5khz)
      begin
       if(nege_edge)
        cnt3 <= 7'b0;
       else if(cnt3!=7'd100)
        cnt3 <= cnt3 + 7'd1;
      end 
       
   always @(posedge sysclk or negedge reset)
    if(~reset)
     begin
      key_on_r <= 2'b11;
      key_on_rr <= 2'b11;
     end   
    else if(clk5khz&& cnt3==7'd100)
     begin 
      key_on_r <= key;
      key_on_rr <= key_on_r;
     end 
   //  ????????????  
   assign key_on = (~key_on_r & key_on_rr);
      
   //  ?????????????
   always @(posedge sysclk or negedge reset)
    if(~reset)
      en <= 1'b0;
    else if(clk5khz && key_on[1])
       en <= ~en;
   
   always @(posedge sysclk or negedge reset)
    if(~reset)
      ss <= 1'b1;
    else if(clk5khz && key_on[0])
       ss <= ~ss; 
  
  assign led[1] = ~en;
  assign led[0] = ss;        
  
  //   ?????sclk??
  always @ (posedge sysclk or negedge reset)
   if(~reset)
     cnt <= 2'b0;
   else if(cnt == 2'd3)
     cnt <= 2'b0;
   else
     cnt <= cnt + 2'd1; 
  assign sclk2=(cnt==2'd3);  
  
  //  sclk??????
  always @(posedge sysclk or negedge reset)
   if(~reset)
    cnt1 <= 6'b0;
   else if(en)
    cnt1 <= cnt1 +6'd1;
    
  wire clk1 = (cnt1 == 6'b111111);
  //  ?????????  
  always @(posedge clk1 or negedge reset) 
   if(~reset)
    addr <= 5'd0;
   else if(en)
    addr <= addr + 5'd1;
    
  always @(posedge sclk2 or negedge reset)
   if(~reset)
    count <= 5'd0;
   else if(en)
    count <= count + 5'd1;
   
   always @(posedge sclk2 or negedge reset)
    if(~reset)
      sclk <= 1'b1;
    else 
     sclk <= ~ sclk;
     
         
   always @(posedge sclk2 or negedge reset)
   if (~reset)
    begin
     shifter <= 8'b0;
     mosi <= 1'bz;
     end
   else if(en)
   case(count)
   4'd1:  shifter <= {shifter[6:0],miso}; 
   4'd3:  shifter <= {shifter[6:0],miso};
   4'd5:  shifter <= {shifter[6:0],miso};
   4'd7:  shifter <= {shifter[6:0],miso};
   4'd9:  shifter <= {shifter[6:0],miso};
   4'd11: shifter <= {shifter[6:0],miso};
   4'd13: shifter <= {shifter[6:0],miso};
   4'd15: begin
            shifter <= {shifter[6:0],miso};
            shifter <= data;    //  ????  
          end  
   default:mosi <= shifter[7];  //  ???????
   endcase 
  else
    mosi <= 1'bz; 
        
  
  always @(addr)
  case(addr)         //  ??????
  5'd0: data = 8'b0000_1111;
  5'd1: data = 8'b0000_1111;
  5'd2: data = 8'b0000_1111;
  5'd3: data = 8'b0000_1111;
  5'd4: data = 8'b0000_1111;
  5'd5: data = 8'b0000_1111;
  5'd6: data = 8'b0000_1111;
  5'd7: data = 8'b0000_1111;  
  5'd8: data = 8'b0000_1111;
  5'd9: data = 8'b0000_1111;
  5'd10:data = 8'b0000_1111;
  5'd11:data = 8'b0000_1111;
  5'd12:data = 8'b0000_1111;
  5'd13:data = 8'b0000_1111;
  5'd14:data = 8'b0000_1111;
  5'd15:data = 8'b0000_1111;
  5'd16:data = 8'b0000_1111;
  5'd17:data = 8'b0000_1111;
  5'd18:data = 8'b0000_1111;
  5'd19:data = 8'b0000_1111;
  5'd20:data = 8'b0000_1111;
  5'd21:data = 8'b0000_1111;
  5'd22:data = 8'b0000_1111;
  5'd23:data = 8'b0000_1111;
  5'd24:data = 8'b0000_1111;
  5'd25:data = 8'b0000_1111;
  5'd26:data = 8'b0000_1111;
  5'd27:data = 8'b0000_1111;
  5'd28:data = 8'b0000_1111;
  5'd29:data = 8'b0000_1111;
  5'd30:data = 8'b0000_1111;
  5'd31:data = 8'b0000_1111;
  default:data = 8'b0000_1111;
  endcase
endmodule     
  
  

测试代码:

`timescale 1ns/1ns
module spi_test ;
reg		sysclk;
reg   reset;
reg   [1:0] key;
reg   miso;
wire  mosi;
wire  sclk;
wire  ss;
wire  [1:0]  led;


spi_master spi(.sysclk(sysclk),
					.key(key),
					.reset(reset),
					.mosi(mosi),
					.miso(miso),
					.sclk(sclk),
					.ss(ss),
					.led(led)
			       );
					
initial
begin
#0  sysclk = 1'b0;
#0  reset  = 1'b0;
#10 reset  = 1'b1;
end

initial
begin
#0        key = 2'b11;
#200      key = 2'b10;
#7000_000 key = 2'b11;
#8000_000 key = 2'b01;
#15000000 key = 2'b11;
end

always #5 sysclk = ~sysclk;
reg  [2:0]  cnt5;



 

   always @(posedge sclk or negedge reset)
   if(~reset)
    cnt5 <= 3'b0;
   else
    cnt5 <= cnt5 + 3'd1;
    
   always @(*)
   case(cnt5)
   3'd0: miso = 1'b0;
   3'd1: miso = 1'b1;
   3'd2: miso = 1'b0;
   3'd3: miso = 1'b1;
   3'd4: miso = 1'b0;
   3'd5: miso = 1'b1;
   3'd6: miso = 1'b0;
   3'd7: miso = 1'b1;
   default:miso=1'b0;
   endcase
   
endmodule
       

网上来的,还有一个slave参考代码(有可能是上面master对应实验时用的slave???)如下:

//use SPI 3 mode,CHOL = 1,CHAL = 1
module spi(input clk,
              input rst_n,
              input CS_N,
              input SCK,
              input MOSI,
              input [7:0] txd_data,
              output reg MISO,
              output reg [7:0] rxd_data,
              output rxd_flag);
 
//-------------------------capture the sck-----------------------------       
reg sck_r0,sck_r1;
wire sck_n,sck_p;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            sck_r0 <= 1'b1;   //sck of the idle state is high 
            sck_r1 <= 1'b1;
        end
    else
        begin
            sck_r0 <= SCK;
            sck_r1 <= sck_r0;
        end
end
 
assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0;   //capture the sck negedge
assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0;   //capture the sck posedge
 
//-----------------------spi_slaver read data-------------------------------
reg rxd_flag_r;
reg [2:0] rxd_state;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            rxd_data <= 1'b0;
            rxd_flag_r <= 1'b0;
            rxd_state <= 1'b0;
        end
    else if(sck_p && !CS_N)   
        begin
            case(rxd_state)
                3'd0:begin
                        rxd_data[7] <= MOSI;
                        rxd_flag_r <= 1'b0;   //reset rxd_flag
                        rxd_state <= 3'd1;
                      end
                3'd1:begin
                        rxd_data[6] <= MOSI;
                        rxd_state <= 3'd2;
                      end
                3'd2:begin
                        rxd_data[5] <= MOSI;
                        rxd_state <= 3'd3;
                      end
                3'd3:begin
                        rxd_data[4] <= MOSI;
                        rxd_state <= 3'd4;
                      end
                3'd4:begin
                        rxd_data[3] <= MOSI;
                        rxd_state <= 3'd5;
                      end
                3'd5:begin
                        rxd_data[2] <= MOSI;
                        rxd_state <= 3'd6;
                      end
                3'd6:begin
                        rxd_data[1] <= MOSI;
                        rxd_state <= 3'd7;
                      end
                3'd7:begin
                        rxd_data[0] <= MOSI;
                        rxd_flag_r <= 1'b1;  //set rxd_flag
                        rxd_state <= 3'd0;
                      end
                default: ;
            endcase
        end
end
 
 
//--------------------capture spi_flag posedge--------------------------------
reg rxd_flag_r0,rxd_flag_r1;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            rxd_flag_r0 <= 1'b0;
            rxd_flag_r1 <= 1'b0;
        end
    else
        begin
            rxd_flag_r0 <= rxd_flag_r;
            rxd_flag_r1 <= rxd_flag_r0;
        end
end
 
assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;   
 
//---------------------spi_slaver send data---------------------------
reg [2:0] txd_state;
always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        begin
            txd_state <= 1'b0;
        end
    else if(sck_n && !CS_N)
        begin
            case(txd_state)
                3'd0:begin
                        MISO <= txd_data[7];
                        txd_state <= 3'd1;
                      end
                3'd1:begin
                        MISO <= txd_data[6];
                        txd_state <= 3'd2;
                      end
                3'd2:begin
                        MISO <= txd_data[5];
                        txd_state <= 3'd3;
                      end
                3'd3:begin
                        MISO <= txd_data[4];
                        txd_state <= 3'd4;
                      end
                3'd4:begin
                        MISO <= txd_data[3];
                        txd_state <= 3'd5;
                      end
                3'd5:begin
                        MISO <= txd_data[2];
                        txd_state <= 3'd6;
                      end
                3'd6:begin
                        MISO <= txd_data[1];
                        txd_state <= 3'd7;
                      end
                3'd7:begin
                        MISO <= txd_data[0];
                        txd_state <= 3'd0;
                      end
                default: ;
            endcase
        end
end
 
endmodule

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!