FPGA – How to Assign a 256-bit std_logic_vector Input

aesfpgavhdlvivado

I realized an AES-256 algorithm which encrypts a 128-bit std_logic_vector (plain_text) with a 256-bit std_logic_vector (master_key). I made a test-bench in order to verify the behavior of the encryption process, and now I would like to implement this algorithm on my Basys3 board (I use Vivado as IDE). My questions are:

How can I map the input vectors? Should I declare signals in my architecture, knowing that I do not have enough I/O ports?

Best Answer

A serial interface uses the least amount of pins. From all the serial interfaces SPI is the easiest to implement. (I think it is about five lines of code). As an SPI interface streams data in and out at the same time you can also use it to read the result.


Ok, I just tried and it was a bit more then five lines mostly dealing with the synchronisation of the SPI signals to an (internal higher frequency) system clock.

The following code was quickly hacked together and seems to work:

//
// Simple dumb SPI interface:
// one big long shift register
// Relies on a system clock which is 
// much faster then the SPI clock
//
// User MUST send the right amount of bits in one go.
//

module spi_dumb 
#(parameter DW   = 128) // Number of internal data bits
  ( 
    // Usual system signals
    input  clk,     // system clock
    input  reset_n, // system reset

    // SPI interface
    input  sclk,
    input  sel_n,
    input  mosi,
    output miso,

    // Internal data interface
    input      [DW-1:0] par_tx, // Data to transmit
    output reg [DW-1:0] par_rx, // Data received
    output reg          valid   // Data has arrived
  );

reg  sclk_meta,sclk_sync,sclk_prev;
reg  seln_meta,seln_sync,seln_prev;
wire clock_edge;

//   assign clock_edge = ~sclk_prev &  sclk_sync; // Rising edge
   assign clock_edge =  sclk_prev & ~sclk_sync; // Falling edge

   always @(posedge clk or negedge reset_n)
   begin
      if (!reset_n)
      begin
         valid     <= 1'b0;
         sclk_meta <= 1'b0;
         sclk_sync <= 1'b0;
         sclk_prev <= 1'b0;
         seln_meta <= 1'b0;
         seln_sync <= 1'b0;
         seln_prev <= 1'b0;
      end
      else
      begin
         // Sychronise the clkc and select
         sclk_meta <= sclk;
         sclk_sync <= sclk_meta;
         sclk_prev <= sclk_sync;
         seln_meta <= sel_n;
         seln_sync <= seln_meta;
         seln_prev <= seln_sync;

         // On falling edge SPI-Select load the shift register
         if (seln_prev & ~seln_sync)
         begin
            par_rx <= par_tx;
            valid  <= 1'b0;
         end

         // On rising edge SPI-Select mark the data as valid
         if (~seln_prev & seln_sync)
            valid  <= 1'b1;

         // If SPI select is low and we have a clock edge pick up the data
         // We assume the mosi data is stable by then
         // (~Two system clocks after SPI clock edge)
         if (!seln_prev && clock_edge)
           par_rx <= {par_rx[DW-2:0],mosi};
      end
   end

   assign miso = par_rx[DW-1];

endmodule    

/*
 * 
 * Auto generated testbench, generated Wed Jun 20 11:04:23 2018
 * post edited
 *
 */

module spi_dumb_test;

localparam CLK_PERIOD=100;

localparam DW= 128;


    // Usual system signals
reg           clk; // system clock
reg           reset_n; // system reset

    // SPI interface
reg           sclk;
reg           sel_n;
reg           mosi;
wire          miso;

    // Internal data interface
reg  [DW-1:0] par_tx; // Data to transmit
wire [DW-1:0] par_rx; // Data received
wire          valid;

integer bit_count;
reg  [DW-1:0] master_tx; // Data to transmit
reg  [DW-1:0] master_rx; // Data received

   initial
   begin
    // Usual system signals
      reset_n  = 1'b0;

    // SPI interface
      sclk     = 1'b0;
      sel_n    = 1'b1;
      mosi     = 1'b0;

    // Internal data interface
      par_tx   = 'b0;
      #(5*CLK_PERIOD) reset_n=1'b1;



      #(5*CLK_PERIOD) sel_n = 1'b0;

      par_tx    = 128'h12345678_11111111_87654321_A5C33C5A;
      master_tx = 128'h23242526_34353637_45464748_56575859;

      for (bit_count=0; bit_count<128; bit_count=bit_count+1)
      begin
         #(5*CLK_PERIOD) ;

         // Tx & RX master emulation, MS bits first
         mosi = master_tx[DW-bit_count-1];
         master_rx[DW-bit_count-1] = miso;
         sclk = 1'b1;
         #(5*CLK_PERIOD) ;
         sclk = 1'b0;
      end
      #(5*CLK_PERIOD) ;
      sel_n = 1'b1;

      #(50*CLK_PERIOD) $stop;
   end


spi_dumb
   #( .DW (DW) ) // parameters
spi_dumb_0 (

    // Usual system signals
      .clk    (clk),     // system clock
      .reset_n(reset_n), // system reset

    // SPI interface
      .sclk   (sclk),
      .sel_n  (sel_n),
      .mosi   (mosi),
      .miso   (miso),

    // Internal data interface
      .par_tx (par_tx),  // Data to transmit
      .par_rx (par_rx),  // Data received
      .valid  (valid) 
   );

   // Generate clock.
   initial
   begin
      clk = 1'b0;
      forever
         #(CLK_PERIOD/2) clk = ~clk;
   end

endmodule

Post edit 2-7-18: found that begin end pair was missing.