MAX10 & Arduino SPI通信 (3)通信テスト【FPGA プログラム】

元記事はこちら

プログラムはメインとSPIコントロール用に2種類あります。

メインプログラム中にシグナルタップ用の周波数逓倍回路(PLL)が組み込まれてますが、削除して問題ないです。PLL回路を入れたまま試す場合は、IPコアよりALTPLLを呼び出して周波数クロック48MHzの4倍、192MHzとなるよう設定してください。

メインモジュール


//MAX10_FB
module main(
  //system
  input wire  RST,        //48MHz PIN
  input wire  CLK,        //PIN 27
  
  output  wire  LED_R,        //PIN 120
  output  wire  LED_G,        //PIN 121
  output  wire  LED_B,        //PIN 122
  
  //SPI
  input wire    SCK,        //8MHz  PIN
  output  wire    MISO,       //PIN
  input wire    MOSI,       //PIN
  input wire  SS,         //PIN
  
  //LED
  output  wire  [0:7] ROW,    //PIN
  output  wire  [0:7] COL     //PIN



);


/**********************  REGSITER  **********************/
reg     [19:0]    COUNTER;

//regster
reg   [0:7]   AD;
reg   [0:7]   LEDR_reg;
reg   [0:7]   LEDG_reg;
reg   [0:7]   LEDB_reg;

reg         DOT_CNT;
reg   [0:7]   DOT_0;
reg   [0:7]   DOT_1;
reg   [0:7]   DOT_2;
reg   [0:7]   DOT_3;
reg   [0:7]   DOT_4;
reg   [0:7]   DOT_5;
reg   [0:7]   DOT_6;
reg   [0:7]   DOT_7;

//SPI control
reg   [0:7]   R_BYTE;
reg         RDt_rst;
reg         nR_W;

//SPI
reg         WDtrig;
//reg         WDt_rst;

reg   [0:7]   Rdata;

//LEDRGB
reg   [0:7]   LEDR;
reg   [0:7]   LEDG;
reg   [0:7]   LEDB;
reg   [0:7]   LEDR_C;
reg   [0:7]   LEDG_C;
reg   [0:7]   LEDB_C;

//8*8 DOT LED
reg   [0:3]   ROW_CNT;



/**********************    WIRE    **********************/
//SPI
wire        SS_sel;
wire        RDtrig;
wire  [0:7]   R_Data;
wire  [0:7]   W_Data;



/////////////////////////////////////////////////////////

//480kHzカウンター
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        COUNTER <= 20'b0;
    end
    else if(COUNTER >= 48000)begin
        COUNTER <= 20'b0;
    end
    else begin
        COUNTER <= COUNTER + 1'b1;
    end
end


/////////////////////////////////////////////////////////
// RGB LED
/////////////////////////////////////////////////////////


//LEDR counter
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDR_C <= 8'b0;
    end
    else if(LEDR_reg == 8'h00)begin
        LEDR_C <= 8'b0;
    end
    else begin
        LEDR_C <= LEDR_C + 1'b1;
    end
end

//LEDR
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDR <= 1'b1;
    end
    else if(LEDR_C < LEDR_reg)begin
        LEDR <= 1'b0;
    end
    else begin
        LEDR <= 1'b1;
    end
end


//LEDG counter
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDG_C <= 8'b0;
    end
    else if(LEDG_reg == 8'h00)begin
        LEDG_C <= 8'b0;
    end
    else begin
        LEDG_C <= LEDG_C + 1'b1;
    end
end

//LEDG
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDG <= 1'b1;
    end
    else if(LEDG_C < LEDG_reg)begin
        LEDG <= 1'b0;
    end
    else begin
        LEDG <= 1'b1;
    end
end


//LEDB counter
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDB_C <= 8'b0;
    end
    else if(LEDB_reg == 8'h00)begin
        LEDB_C <= 8'b0;
    end
    else begin
        LEDB_C <= LEDB_C + 1'b1;
    end
end

//LEDB
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDB <= 1'b1;
    end
    else if(LEDB_C < LEDB_reg)begin
        LEDB <= 1'b0;
    end
    else begin
        LEDB <= 1'b1;
    end
end


assign LED_R = LEDR;
assign LED_G = LEDG;
assign LED_B = LEDB;


/////////////////////////////////////////////////////////
// 8*8 DOT LED
/////////////////////////////////////////////////////////


always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        ROW_CNT <= 4'b0;
    end
    else if(DOT_CNT == 1'b0)begin
        ROW_CNT <= 4'b0;
    end
    else if( COUNTER >= 48000 )begin
        if(ROW_CNT >= 4'd8)begin
          ROW_CNT <= 4'b1;
        end
        else begin
          ROW_CNT <= ROW_CNT + 1'b1;
        end
    end
    else begin
        ROW_CNT <= ROW_CNT;
    end
end

assign COL = (ROW_CNT == 4'd0)  ? 8'h00:
      ((ROW_CNT == 4'd1)  ? DOT_0:
      ((ROW_CNT == 4'd2)  ? DOT_1:
      ((ROW_CNT == 4'd3)  ? DOT_2:
      ((ROW_CNT == 4'd4)  ? DOT_3:
      ((ROW_CNT == 4'd5)  ? DOT_4:
      ((ROW_CNT == 4'd6)  ? DOT_5:
      ((ROW_CNT == 4'd7)  ? DOT_6:
      ((ROW_CNT == 4'd8)  ? DOT_7:
      8'h000))))))));
      
assign ROW = (ROW_CNT == 4'd0)  ? 8'h00:
      ((ROW_CNT == 4'd1)  ? 8'b0000_0001:
      ((ROW_CNT == 4'd2)  ? 8'b0000_0010:
      ((ROW_CNT == 4'd3)  ? 8'b0000_0100:
      ((ROW_CNT == 4'd4)  ? 8'b0000_1000:
      ((ROW_CNT == 4'd5)  ? 8'b0001_0000:
      ((ROW_CNT == 4'd6)  ? 8'b0010_0000:
      ((ROW_CNT == 4'd7)  ? 8'b0100_0000:
      ((ROW_CNT == 4'd8)  ? 8'b1000_0000:
      8'h000))))))));

/////////////////////////////////////////////////////////
// registeres
/////////////////////////////////////////////////////////

//
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        AD <= 8'b0;
    end
    else if( (R_BYTE == 8'h00) && RDtrig )begin
        AD <= R_Data;
    end
    else begin
        AD <= AD;
    end
end

//AD(00)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDR_reg <=8'b0;
    end
    else if((AD==8'h00) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        LEDR_reg <= R_Data;
    end
    else begin
        LEDR_reg <= LEDR_reg;
    end
end

//AD(01)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDG_reg <= 8'b0;
    end
    else if((AD==8'h01) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        LEDG_reg <= R_Data;
    end
    else begin
        LEDG_reg <= LEDG_reg;
    end
end

//AD(02)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        LEDB_reg <= 8'b0;
    end
    else if((AD==8'h02) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        LEDB_reg <= R_Data;
    end
    else begin
        LEDB_reg <= LEDB_reg;
    end
end

//AD(08)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_CNT <= 1'b0;
    end
    else if((AD==8'h08) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_CNT <= R_Data[7];
    end
    else begin
        DOT_CNT <= DOT_CNT;
    end
end

//AD(10)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_0 <= 8'b0;
    end
    else if((AD==8'h10) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_0 <= R_Data;
    end
    else begin
        DOT_0 <= DOT_0;
    end
end

//AD(11)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_1 <= 8'b0;
    end
    else if((AD==8'h11) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_1 <= R_Data;
    end
    else begin
        DOT_1 <= DOT_1;
    end
end

//AD(12)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_2 <= 8'b0;
    end
    else if((AD==8'h12) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_2 <= R_Data;
    end
    else begin
        DOT_2 <= DOT_2;
    end
end

//AD(13)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_3 <= 8'b0;
    end
    else if((AD==8'h13) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_3 <= R_Data;
    end
    else begin
        DOT_3 <= DOT_3;
    end
end

//AD(14)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_4 <= 8'b0;
    end
    else if((AD==8'h14) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_4 <= R_Data;
    end
    else begin
        DOT_4 <= DOT_4;
    end
end

//AD(15)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_5 <= 8'b0;
    end
    else if((AD==8'h15) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_5 <= R_Data;
    end
    else begin
        DOT_5 <= DOT_5;
    end
end

//AD(16)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_6 <= 8'b0;
    end
    else if((AD==8'h16) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_6 <= R_Data;
    end
    else begin
        DOT_6 <= DOT_6;
    end
end

//AD(17)
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        DOT_7 <= 8'b0;
    end
    else if((AD==8'h17) && RDtrig && nR_W && (R_BYTE==8'd3))begin
        DOT_7 <= R_Data;
    end
    else begin
        DOT_7 <= DOT_7;
    end
end

assign W_Data = (AD==8'h00)  ? LEDR_reg:
        ((AD==8'h01) ? LEDG_reg:
        ((AD==8'h02) ? LEDB_reg:
        ((AD==8'h08) ? DOT_CNT:
        ((AD==8'h10) ? DOT_0:
        ((AD==8'h11) ? DOT_1:
        ((AD==8'h12) ? DOT_2:
        ((AD==8'h13) ? DOT_3:
        ((AD==8'h14) ? DOT_4:
        ((AD==8'h15) ? DOT_5:
        ((AD==8'h16) ? DOT_6:
        ((AD==8'h17) ? DOT_7:
        8'h00))) ) )))))));

/////////////////////////////////////////////////////////
// SPI Control
/////////////////////////////////////////////////////////

//受信トリガ
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        RDt_rst <= 1'b0;
    end
    else if(RDtrig)begin
        RDt_rst <= 1'b1;
    end
    else begin
        RDt_rst <= 1'b0;
    end
end

//リード/ライト
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        nR_W <= 1'b0;
    end
     else if(SS)begin
        nR_W <= 1'b0;
    end
    else if((R_BYTE==8'd1) && RDtrig)begin
        nR_W <= R_Data[7];
    end
end

//送信データ
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        WDtrig <= 1'b0;
    end
     else if( SS )begin
        WDtrig <= 1'b0;
    end
    else if(R_BYTE==8'd2)begin
        WDtrig <= 1'b1;
    end
    else begin
        WDtrig <= WDtrig;
    end
end

//バイト数
always @(posedge CLK or negedge RST)
begin
    if(~RST)begin
        R_BYTE <= 8'b0;
    end
    else if(SS)begin
        R_BYTE <= 8'b0;
    end
    else if(RDtrig && ~RDt_rst)begin
        R_BYTE <= R_BYTE + 1'b1;
    end
    else begin
        R_BYTE <= R_BYTE;
    end
end

assign SS_sel = SS;

//SPIモジュール
mySPI mySPI (
  //system
  .RST    (RST),
  .CLK    (CLK),
  
  
  .SCK    (SCK),
  .MOSI   (MOSI),
  .MISO   (MISO),
  .SS     (SS_sel),
  
  .WDtrig   (WDtrig),       //input     準備できたらHIGHにする
  .WData    (W_Data),       //input [7:0] 送信データ
  
  
  .RDtrig   (RDtrig),       //output    受信したらHIGHなる
  .RDt_rst  (RDt_rst),        //input     受信完了
  .RData    (R_Data)        //output[7:0] 受信データ

);



wire        CLK98M;
wire        locked;

pll pll (
  .areset   (~RST),
  .inclk0   (CLK),
  .c0     (CLK98M),
  .locked   (locked)
  
);



endmodule

SPIモジュール


module mySPI (
  //system
  input wire      RST,
  input wire      CLK,
  
  //SPI
  input wire      SCK,
  input wire      MOSI,
  output  reg       MISO,
  input wire      SS,
  
  //MISO
  input wire      WDtrig,
//  output  wire      WDt_rst,
  input wire  [0:7] WData,
  
  //MOSI
  output  reg       RDtrig,
  input wire      RDt_rst,
  output  wire  [0:7] RData

);

/**********************  REGSITER  **********************/

reg   [0:1]   SCK_EDGE;
reg   [0:3]   BYTE_counter;

reg   [0:7]   READ_DATA;
reg   [0:7]   WRITE_DATA;

/**********************    WIRE    **********************/

wire  [0:1]   sck_load;
wire  [0:1]   sck_latch;


/***************************************************
SPI interface

CHAP = 0
SCK1クロック始めでデータのロード、次のでラッチ
CPOL = 0:立上がりロード、立下りラッチ
CPOL = 1:立下りロード、立上がりラッチ

CHAP = 1
SCK1クロック始めでデータのロード、次のでラッチ
但し、FPGA側のMISOはSSと同時にデータをロード
CPOL = 0:立下りロード、立上がりラッチ
CPOL = 1:立上がりロード、立下りラッチ

***************************************************/
parameter CPHA = 0;
parameter CPOL = 0;

assign  sck_load =  (CPHA == 0) ?   ((CPOL == 0) ? 2'b10: 2'b01):
                  ((CPOL == 0) ? 2'b01: 2'b10);

assign  sck_latch = (CPHA == 0) ?   ((CPOL == 0) ? 2'b01: 2'b10):
                  ((CPOL == 0) ? 2'b10: 2'b01);


/////////////////////////////////////////////////////////

//SCKエッジ
always @(posedge CLK or negedge RST)
begin
  if(~RST)begin
    SCK_EDGE <= 2'b0;
  end
  else begin
    SCK_EDGE <= {SCK_EDGE[1],SCK};
  end
end

//ビット数カウンタ
always @(posedge CLK or negedge RST)
begin
  if(~RST)begin
    BYTE_counter <= 4'b0;
    RDtrig <= 1'b0;
  end
  else if( SS )begin
    BYTE_counter <= 4'b0;
    RDtrig <= 1'b0;
  end
  else if( RDt_rst )begin
    RDtrig <= 1'b0;
  end
  else if( (BYTE_counter >= 4'd8) && (SCK_EDGE == sck_load) )begin
    BYTE_counter <= 4'b0;
    RDtrig <= 1'b1;
  end
  else if( SCK_EDGE == sck_latch )begin
    BYTE_counter <= BYTE_counter + 1'b1;
  end
  else begin
    BYTE_counter <= BYTE_counter;
    RDtrig <= RDtrig;
  end
end

//MOSI 受信データ
always @(posedge CLK or negedge RST)
begin
  if(~RST)begin
    READ_DATA <= 8'b0;
  end
  else if( SS || RDt_rst)begin
    READ_DATA <= 8'b0;
  end 
  else if( SCK_EDGE == sck_latch )begin
    READ_DATA <= {READ_DATA[1:7],MOSI};
  end
  else begin
    READ_DATA <= READ_DATA;
  end
end

//受信データ 送り
assign  RData = (RDtrig == 1) ? READ_DATA : 8'h00;


//MISO 送信データ
always @(posedge CLK or negedge RST)
begin
  if(~RST)begin
    WRITE_DATA <= 8'b0;
  end
  else if( SS )begin
    WRITE_DATA <= 8'b0;
  end
  else if( WDtrig )begin
    WRITE_DATA <= WData;
  end
  else begin
    WRITE_DATA <= WRITE_DATA;
  end
end

//送信データ 送り
always @(posedge CLK or negedge RST)
begin
  if(~RST)begin
    MISO <= 1'b0;
  end
  else if( SS )begin
    MISO <= 1'b0;
  end
  else if( SCK_EDGE == sck_load )begin
    MISO <= WRITE_DATA[BYTE_counter];
  end
  else if( (CPHA == 0) && (BYTE_counter==0) )begin
    MISO <= WRITE_DATA[0];
  end
  else begin
    MISO <= MISO;
  end
end

endmodule

 

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中