Friday 19 February 2016

fpga - How can I assign a 256-bit std_logic_vector input


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?




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.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...