使用Vitis HLS实现和优化SPECK加解密函数
设计代码如下:
// speck_hls.cpp
#include "ap_int.h"
// 定义密钥和回合数
#define WORD_SIZE 16
#define KEY_SIZE 4
#define NUM_ROUNDS 22
typedef ap_uint<WORD_SIZE> half_word;
typedef ap_uint<WORD_SIZE*2> word;
typedef ap_uint<WORD_SIZE*4> key_type;
// 定义流水线节拍
#define PIPELINE_II 1
// SPECK加密算法
void speck_encrypt(word plaintext, word* ciphertext, const half_word key_schedule[NUM_ROUNDS]) {
half_word left = plaintext(WORD_SIZE*2-1, WORD_SIZE);
half_word right = plaintext(WORD_SIZE-1, 0);
SPECK_ENCRYPT_LOOP:
for (int i = 0; i < NUM_ROUNDS; i++) {
#pragma HLS PIPELINE II=PIPELINE_II
left = (right + left) % (1 << WORD_SIZE);
left ^= key_schedule[i];
right = (right >> 7) | (right << (WORD_SIZE - 7));
right ^= left;
}
*ciphertext = (left, right);
}
// SPECK解密算法
void speck_decrypt(word ciphertext, word* plaintext, const half_word key_schedule[NUM_ROUNDS]) {
half_word left = ciphertext(WORD_SIZE*2-1, WORD_SIZE);
half_word right = ciphertext(WORD_SIZE-1, 0);
SPECK_DECRYPT_LOOP:
for (int i = NUM_ROUNDS-1; i >= 0; i--) {
#pragma HLS PIPELINE II=PIPELINE_II
right ^= left;
right = (right << 7) | (right >> (WORD_SIZE - 7));
left ^= key_schedule[i];
left = (left - right) % (1 << WORD_SIZE);
}
*plaintext = (left, right);
}
// 密钥扩展
void key_expansion(const key_type key, half_word key_schedule[NUM_ROUNDS]) {
half_word l[NUM_ROUNDS];
half_word k = key(KEY_SIZE*WORD_SIZE-1, (KEY_SIZE-1)*WORD_SIZE);
l[0] = key((KEY_SIZE-2)*WORD_SIZE-1, (KEY_SIZE-3)*WORD_SIZE);
key_schedule[0] = k;
KEY_EXPANSION_LOOP:
for (int i = 0; i < NUM_ROUNDS-1; i++) {
#pragma HLS PIPELINE II=PIPELINE_II
l[i+1] = (k + l[i]) % (1 << WORD_SIZE);
l[i+1] ^= i;
k = (k >> 7) | (k << (WORD_SIZE - 7));
k ^= l[i+1];
key_schedule[i+1] = k;
}
}
// 重构的顶层函数
void speck(word plaintext, word* ciphertext, word* decrypted_text, const key_type key) {
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=plaintext
#pragma HLS INTERFACE s_axilite port=ciphertext
#pragma HLS INTERFACE s_axilite port=decrypted_text
#pragma HLS INTERFACE s_axilite port=key
half_word key_schedule[NUM_ROUNDS];
// Key schedule calculation
key_expansion(key, key_schedule);
// 加密和解密操作
word ciphertext_internal;
word decrypted_text_internal;
speck_encrypt(plaintext, &ciphertext_internal, key_schedule);
speck_decrypt(ciphertext_internal, &decrypted_text_internal, key_schedule);
// 将结果写入输出
*ciphertext = ciphertext_internal;
*decrypted_text = decrypted_text_internal;
}测试代码如下:
// test_speck_hls.cpp
#include <iostream>
#include <stdio.h>
#include "ap_int.h"
#define WORD_SIZE 16
#define KEY_SIZE 4
#define NUM_ROUNDS 22
typedef ap_uint<WORD_SIZE> half_word;
typedef ap_uint<WORD_SIZE*2> word;
typedef ap_uint<WORD_SIZE*4> key_type;
void speck(word plaintext, word* ciphertext, word* decrypted_text, const key_type key);
// 自动化测试函数
bool run_test(word plaintext, const key_type key) {
word ciphertext;
word decrypted_text;
// 调用SPECK函数进行加密和解密
speck(plaintext, &ciphertext, &decrypted_text, key);
// 检查解密结果是否与原始明文匹配
return (plaintext == decrypted_text);
}
int main() {
// 测试数据
word plaintexts[] = {0x6574694c, 0x12345678, 0xABCDEF01, 0x0FEDCBA9};
key_type keys[] = {0x1918111009080100, 0x1A1B1C1D0E0F1011, 0x2021222324252627, 0x1314151607181920};
int num_tests = sizeof(plaintexts) / sizeof(plaintexts[0]);
// 记录通过和失败的测试数量
int passed_tests = 0;
int failed_tests = 0;
// 测试每组明文和密钥
for (int i = 0; i < num_tests; i++) {
bool result = run_test(plaintexts[i], keys[i]);
if (result) {
passed_tests++;
printf("Test %d passed\n", i+1);
} else {
failed_tests++;
printf("Test %d failed\n", i+1);
}
}
printf("Total tests passed: %d\n", passed_tests);
printf("Total tests failed: %d\n", failed_tests);
return 0;
}编译结果:





