//
// RAM initialization section of the RC5 cryptographic chip
// design.
//
`define READ 0
`define WRITE 1
`define BAD_STATE 0
`define RESET 1
`define CRYPT_INIT 2
`define INIT_DONE 3
`define SHIFT_SETUP 4
`define ENCRYPT 5
//
// RAM memory
//
module RamTable( clk, address, data_in, r_w, data_out );
parameter TableSize = 32;
parameter DataWidth = 32;
parameter BitsInAddr = 5;
input clk;
input [BitsInAddr-1 : 0] address;
input [DataWidth-1 : 0] data_in;
input r_w;
output [DataWidth-1 : 0] data_out;
reg [DataWidth-1 : 0] data_out;
reg [DataWidth-1:0] Table[TableSize-1:0];
always @(posedge clk )
begin
// $write("%t: RamTable: address = %d", $time, address );
if (r_w) // do a write
begin : if_block
// $write(", data = %x", data_in );
Table[ address ] <= data_in;
end
// $display("");
data_out <= Table[ address ];
end
initial
begin : init
integer i;
for (i = 0; i < TableSize; i = i + 1)
Table[ i ] = 0;
end
endmodule // RamTable
module RAM_mux( rom_data, shift_data, crypt_data, /* ram input data sources */
rw_rom, rw_shift, rw_crypt, /* input r/w controls */
addr_rom, addr_shift, addr_crypt, /* input addresses */
chip_state,
ram_data, /* input data to RAM */
ram_rw, /* RAM r/w control */
ram_addr /* ram address */
);
parameter DataWidth = 32;
parameter BitsInAddr = 5;
input [DataWidth-1 : 0] rom_data, shift_data, crypt_data;
input rw_rom, rw_shift, rw_crypt;
input [BitsInAddr-1 : 0] addr_rom, addr_shift, addr_crypt;
input [1:0] chip_state;
output [DataWidth-1 : 0] ram_data;
output ram_rw;
output [BitsInAddr-1 : 0] ram_addr;
reg [DataWidth-1 : 0] ram_data;
reg ram_rw;
reg [BitsInAddr-1 : 0] ram_addr;
// data mux
always @( chip_state or rom_data or shift_data or crypt_data )
begin
case (chip_state)
`CRYPT_INIT : ram_data = rom_data;
`SHIFT_SETUP : ram_data = shift_data;
`ENCRYPT : ram_data = crypt_data;
default : ram_data = 32'hz;
endcase
end
// rw mux
always @( chip_state or rw_rom or rw_shift or rw_crypt )
begin
case (chip_state)
`CRYPT_INIT : ram_rw = rw_rom;
`SHIFT_SETUP : ram_rw = rw_shift;
`ENCRYPT : ram_rw = rw_crypt;
default : ram_rw = 32'hz;
endcase
end
// addr mux
always @( chip_state or addr_rom or addr_shift or addr_crypt )
begin
case (chip_state)
`CRYPT_INIT : ram_addr = addr_rom;
`SHIFT_SETUP : ram_addr = addr_shift;
`ENCRYPT : ram_addr = addr_crypt;
default : ram_addr = 32'hz;
endcase
end
endmodule // RAM_mux
module Key( clk, reset, address, r_w, char_in, data_in, data_out );
parameter KeyBytes = 16;
parameter BytesPerWord = 4;
parameter NumWords = KeyBytes / BytesPerWord;
parameter KeyBits = KeyBytes * 8;
parameter AddrWidth = 2;
parameter TRUE = 1;
parameter FALSE = 0;
input clk, reset;
input [ AddrWidth-1 : 0 ] address;
input r_w;
input [7 : 0] char_in;
input [ 31 : 0 ] data_in;
output [ 31 : 0 ] data_out;
reg [ 31 : 0 ] data_out;
reg [ KeyBits-1 : 0 ] crypt_key;
always @(posedge clk or posedge reset)
begin : always_scope
reg [4:0] byte_cnt;
reg init, first_time;
if (reset == 1)
begin
first_time = TRUE;
init = TRUE;
end
else if (clk)
begin
if (init)
begin
if (first_time)
begin
first_time = FALSE;
byte_cnt = 0;
end
else
begin
byte_cnt = byte_cnt + 1;
end
// byte address for the key
case (byte_cnt)
5'd0 : crypt_key[ 7: 0 ] = char_in;
5'd1 : crypt_key[ 15: 8 ] = char_in;
5'd2 : crypt_key[ 23: 16] = char_in;
5'd3 : crypt_key[ 31: 24] = char_in;
5'd4 : crypt_key[ 39: 32] = char_in;
5'd5 : crypt_key[ 47: 40] = char_in;
5'd6 : crypt_key[ 55: 48] = char_in;
5'd7 : crypt_key[ 63: 56] = char_in;
5'd8 : crypt_key[ 71: 64] = char_in;
5'd9 : crypt_key[ 79: 72] = char_in;
5'd10 : crypt_key[ 87: 80] = char_in;
5'd11 : crypt_key[ 95: 88] = char_in;
5'd12 : crypt_key[103: 96] = char_in;
5'd13 : crypt_key[111:104] = char_in;
5'd14 : crypt_key[119:112] = char_in;
5'd15 : crypt_key[127:120] = char_in;
default: init = FALSE;
endcase
end
else // ! init
begin
// word address for the key
if (r_w == `READ)
case (address)
2'd0 : crypt_key[ 31 : 0 ] = data_in;
2'd1 : crypt_key[ 63 : 32] = data_in;
2'd2 : crypt_key[ 95 : 64] = data_in;
2'd3 : crypt_key[127 : 96] = data_in;
endcase
else // r_w == `WRITE
case (address)
2'd0 : data_out = crypt_key[ 31 : 0 ];
2'd1 : data_out = crypt_key[ 63 : 32];
2'd2 : data_out = crypt_key[ 95 : 64];
2'd3 : data_out = crypt_key[127 : 96];
endcase
end // !init
end // clk
end // always
endmodule // Key
module ROM( clk, address, data_out );
parameter TableSize = 32;
parameter DataWidth = 32;
parameter BitsInAddr = 5;
input clk;
input [BitsInAddr-1 : 0] address;
output [DataWidth-1 : 0] data_out;
reg [DataWidth-1 : 0] data_out;
reg [DataWidth-1:0] ROM[ TableSize-1 : 0 ];
always @(posedge clk)
begin
// $display("%t: ROM: addr = %d", $time, address );
// a ROM implemented as a large MUX with
// wired "magic" values
case (address)
0 : data_out <= 32'hb7e15163;
1 : data_out <= 32'h5618cb1c;
2 : data_out <= 32'hf45044d5;
3 : data_out <= 32'h9287be8e;
4 : data_out <= 32'h30bf3847;
5 : data_out <= 32'hcef6b200;
6 : data_out <= 32'h6d2e2bb9;
7 : data_out <= 32'h0b65a572;
8 : data_out <= 32'ha99d1f2b;
9 : data_out <= 32'h47d498e4;
10 : data_out <= 32'he60c129d;
11 : data_out <= 32'h84438c56;
12 : data_out <= 32'h227b060f;
13 : data_out <= 32'hc0b27fc8;
14 : data_out <= 32'h5ee9f981;
15 : data_out <= 32'hfd21733a;
16 : data_out <= 32'h9b58ecf3;
17 : data_out <= 32'h399066ac;
18 : data_out <= 32'hd7c7e065;
19 : data_out <= 32'h75ff5a1e;
20 : data_out <= 32'h1436d3d7;
21 : data_out <= 32'hb26e4d90;
22 : data_out <= 32'h50a5c749;
23 : data_out <= 32'heedd4102;
24 : data_out <= 32'h8d14babb;
25 : data_out <= 32'h2b4c3474;
26 : data_out <= 32'hc983ae2d;
27 : data_out <= 32'h67bb27e6;
28 : data_out <= 32'h05f2a19f;
29 : data_out <= 32'ha42a1b58;
30 : data_out <= 32'h42619511;
31 : data_out <= 32'he0990eca;
endcase
end
endmodule // ROM
//
// RAM_init - RAM initialization control logic
//
module RAM_init( clk, reset, rom_addr, ram_init_addr, r_w, done );
parameter TableSize = 32;
parameter DataWidth = 32;
parameter BitsInAddr = 5;
parameter FALSE = 0;
parameter TRUE = 1;
input clk, reset;
output [BitsInAddr-1 : 0] rom_addr, ram_init_addr;
output r_w, done;
reg [BitsInAddr-1 : 0] rom_addr, ram_init_addr;
reg r_w, done;
reg [3:0] state;
reg first_time;
//
// Send address to ROM
//
always @(posedge clk or posedge reset)
begin
if (reset == 1)
begin
r_w = `READ;
state = `CRYPT_INIT;
done = FALSE;
rom_addr = 0;
ram_init_addr = 0;
first_time = TRUE;
end
else if (state == `CRYPT_INIT)
begin
r_w = `WRITE;
if (first_time)
first_time = FALSE;
else
ram_init_addr <= ram_init_addr + 1;
rom_addr <= rom_addr + 1;
if (ram_init_addr == TableSize )
begin
done = TRUE;
state = `INIT_DONE;
end
end // if CRYPT_INIT
//$display("%t: RAM_init: rom_addr = %d, ram_addr = %d", $time,
// rom_addr, ram_init_addr );
end // always
endmodule // RAM_init
/*
This design is intended to be part of a larger design. So signals
exist that are not driven, since those pieces of the design are not
present here.
*/
module RC5_chip( clk, reset, char_in, char_out );
parameter TableSize = 32;
parameter DataWidth = 32;
parameter BitsInAddr = 5;
input clk, reset;
input [7:0] char_in;
output [7:0] char_out;
wire [BitsInAddr-1 : 0] address, rom_addr, ram_init_addr, addr_shift, addr_crypt;
wire [DataWidth-1 : 0] data_in, rom_data, shift_data, crypt_data;
wire [DataWidth-1 : 0] data_out;
wire ram_init_done, shift_done;
wire r_w, rw_rom, rw_shift, rw_crypt;
wire [ 31 : 0 ] key_data_in;
wire [ 31 : 0 ] key_data_out;
reg [ 1 : 0 ] key_addr;
wire ram_clk;
// RAM is basicly clocked on the negedge of system clock
assign ram_clk = ~clk;
// reg [DataWidth-1 : 0] shift_data, crypt_data;
reg [1:0] chip_state;
// make sure that all undriven signals are grounded
// to avoid pruning by evil Xilinks tools.
assign shift_data = 0,
crypt_data = 0,
rw_shift = 0,
rw_crypt = 0,
addr_shift = 0,
addr_crypt = 0,
shift_done = 0;
RamTable tbl ( ram_clk, address, data_in, r_w, data_out );
RAM_mux ram_bus ( rom_data, shift_data, crypt_data,
rw_rom, rw_shift, rw_crypt,
ram_init_addr, addr_shift, addr_crypt,
chip_state,
data_in,
r_w,
address );
ROM rom ( clk, rom_addr, rom_data );
RAM_init init_cntl ( clk, reset, rom_addr, ram_init_addr, rw_rom, ram_init_done );
Key crypt_key ( clk, reset, key_addr, r_w, char_in, key_data_in, key_data_out );
always @(posedge ram_init_done or posedge shift_done or posedge reset)
begin
if (ram_init_done == 1)
chip_state = `SHIFT_SETUP;
else if (shift_done == 1)
chip_state = `ENCRYPT;
else if (reset == 1)
chip_state = `CRYPT_INIT;
end
endmodule
module check_key( go, key_passed );
parameter TableSize = 32;
parameter FALSE = 0;
parameter TRUE = 1;
input go;
output key_passed;
reg key_passed;
always @(posedge go)
begin : check_key_block
integer i;
key_passed = TRUE;
// check that the key was properly initialized
for (i = 0; i <= TableSize; i = i + 1)
begin
case (i)
5'd0 : if (testbench.design.crypt_key.crypt_key[ 7: 0 ] != testbench.key[15])
key_passed = FALSE;
5'd1 : if (testbench.design.crypt_key.crypt_key[ 15: 8 ] != testbench.key[14])
key_passed = FALSE;
5'd2 : if (testbench.design.crypt_key.crypt_key[ 23: 16] != testbench.key[13])
key_passed = FALSE;
5'd3 : if (testbench.design.crypt_key.crypt_key[ 31: 24] != testbench.key[12])
key_passed = FALSE;
5'd4 : if (testbench.design.crypt_key.crypt_key[ 39: 32] != testbench.key[11])
key_passed = FALSE;
5'd5 : if (testbench.design.crypt_key.crypt_key[ 47: 40] != testbench.key[10])
key_passed = FALSE;
5'd6 : if (testbench.design.crypt_key.crypt_key[ 55: 48] != testbench.key[9])
key_passed = FALSE;
5'd7 : if (testbench.design.crypt_key.crypt_key[ 63: 56] != testbench.key[8])
key_passed = FALSE;
5'd8 : if (testbench.design.crypt_key.crypt_key[ 71: 64] != testbench.key[7])
key_passed = FALSE;
5'd9 : if (testbench.design.crypt_key.crypt_key[ 79: 72] != testbench.key[6])
key_passed = FALSE;
5'd10 : if (testbench.design.crypt_key.crypt_key[ 87: 80] != testbench.key[5])
key_passed = FALSE;
5'd11 : if (testbench.design.crypt_key.crypt_key[ 95: 88] != testbench.key[4])
key_passed = FALSE;
5'd12 : if (testbench.design.crypt_key.crypt_key[103: 96] != testbench.key[3])
key_passed = FALSE;
5'd13 : if (testbench.design.crypt_key.crypt_key[111:104] != testbench.key[2])
key_passed = FALSE;
5'd14 : if (testbench.design.crypt_key.crypt_key[119:112] != testbench.key[1])
key_passed = FALSE;
5'd15 : if (testbench.design.crypt_key.crypt_key[127:120] != testbench.key[0])
key_passed = FALSE;
endcase
end
if (! key_passed)
begin
$display("key improperly initialized");
end
end // always
endmodule // check_key
module check_ram( go, table_passed );
parameter TableSize = 32;
parameter FALSE = 0;
parameter TRUE = 1;
input go;
output table_passed;
reg table_passed;
always @(posedge go)
begin : check_ram_block
integer i;
table_passed = TRUE;
// make sure that the RAM table was initialized properly.
for (i = 0; (i < TableSize) && table_passed;
i = (table_passed) ? i + 1 : i )
begin
case (i)
0 : if (testbench.design.tbl.Table[i] != 32'hb7e15163)
table_passed = FALSE;
1 : if (testbench.design.tbl.Table[i] != 32'h5618cb1c)
table_passed = FALSE;
2 : if (testbench.design.tbl.Table[i] != 32'hf45044d5)
table_passed = FALSE;
3 : if (testbench.design.tbl.Table[i] != 32'h9287be8e)
table_passed = FALSE;
4 : if (testbench.design.tbl.Table[i] != 32'h30bf3847)
table_passed = FALSE;
5 : if (testbench.design.tbl.Table[i] != 32'hcef6b200)
table_passed = FALSE;
6 : if (testbench.design.tbl.Table[i] != 32'h6d2e2bb9)
table_passed = FALSE;
7 : if (testbench.design.tbl.Table[i] != 32'h0b65a572)
table_passed = FALSE;
8 : if (testbench.design.tbl.Table[i] != 32'ha99d1f2b)
table_passed = FALSE;
9 : if (testbench.design.tbl.Table[i] != 32'h47d498e4)
table_passed = FALSE;
10 : if (testbench.design.tbl.Table[i] != 32'he60c129d)
table_passed = FALSE;
11 : if (testbench.design.tbl.Table[i] != 32'h84438c56)
table_passed = FALSE;
12 : if (testbench.design.tbl.Table[i] != 32'h227b060f)
table_passed = FALSE;
13 : if (testbench.design.tbl.Table[i] != 32'hc0b27fc8)
table_passed = FALSE;
14 : if (testbench.design.tbl.Table[i] != 32'h5ee9f981)
table_passed = FALSE;
15 : if (testbench.design.tbl.Table[i] != 32'hfd21733a)
table_passed = FALSE;
16 : if (testbench.design.tbl.Table[i] != 32'h9b58ecf3)
table_passed = FALSE;
17 : if (testbench.design.tbl.Table[i] != 32'h399066ac)
table_passed = FALSE;
18 : if (testbench.design.tbl.Table[i] != 32'hd7c7e065)
table_passed = FALSE;
19 : if (testbench.design.tbl.Table[i] != 32'h75ff5a1e)
table_passed = FALSE;
20 : if (testbench.design.tbl.Table[i] != 32'h1436d3d7)
table_passed = FALSE;
21 : if (testbench.design.tbl.Table[i] != 32'hb26e4d90)
table_passed = FALSE;
22 : if (testbench.design.tbl.Table[i] != 32'h50a5c749)
table_passed = FALSE;
23 : if (testbench.design.tbl.Table[i] != 32'heedd4102)
table_passed = FALSE;
24 : if (testbench.design.tbl.Table[i] != 32'h8d14babb)
table_passed = FALSE;
25 : if (testbench.design.tbl.Table[i] != 32'h2b4c3474)
table_passed = FALSE;
26 : if (testbench.design.tbl.Table[i] != 32'hc983ae2d)
table_passed = FALSE;
27 : if (testbench.design.tbl.Table[i] != 32'h67bb27e6)
table_passed = FALSE;
28 : if (testbench.design.tbl.Table[i] != 32'h05f2a19f)
table_passed = FALSE;
29 : if (testbench.design.tbl.Table[i] != 32'ha42a1b58)
table_passed = FALSE;
30 : if (testbench.design.tbl.Table[i] != 32'h42619511)
table_passed = FALSE;
31 : if (testbench.design.tbl.Table[i] != 32'he0990eca)
table_passed = FALSE;
endcase
end
if (! table_passed)
begin
$display("encryption table improperly initialized");
$display("testbench.design.tbl.Table[%d] = %h", i, testbench.design.tbl.Table[i] );
end
end // always
endmodule // check_ram
//
// Master module to control the write of ROM to RAM and
// to verify that data was written correctly.
//
module testbench;
parameter FALSE = 0;
parameter TRUE = 1;
parameter TableSize = 32;
reg [7:0] key[ 15:0];
reg master_clock, reset;
reg [7:0] char_in;
wire [7:0] char_out;
reg do_key_check, do_ram_check;
wire key_check_rslt, ram_check_rslt;
RC5_chip design ( master_clock, reset, char_in, char_out );
check_key u1 ( do_key_check, key_check_rslt );
check_ram u2 ( do_ram_check, ram_check_rslt );
initial
begin : init
reg passed, key_passed, table_passed;
integer i;
/*
$gr_waves("ram_clk", design.tbl.clk,
"ram_adr", design.tbl.address,
"ram_rw", design.tbl.r_w,
"ram_din", design.tbl.data_in,
"rom_clk", design.rom.clk,
"rom_adr", design.rom.address,
"rom_data", design.rom.data_out );
*/
key_passed = TRUE;
table_passed = TRUE;
passed = TRUE;
key[ 0 ] = "o";
key[ 1 ] = "n";
key[ 2 ] = "e";
key[ 3 ] = "s";
key[ 4 ] = "t";
key[ 5 ] = "e";
key[ 6 ] = "p";
key[ 7 ] = "o";
key[ 8 ] = "v";
key[ 9 ] = "e";
key[10 ] = "r";
key[11 ] = "t";
key[12 ] = "h";
key[13 ] = "e";
key[14 ] = "l";
key[15 ] = "n";
$display("ram_rom_init.v: this test takes a while in software simulation");
master_clock = 1; // start with a negedge clock transition
reset = 0; // toggle the reset line
#1
reset = ~reset; // reset = 1
master_clock = ~master_clock; // clk == 0
#1;
reset = 0;
// clock the ROM to RAM transfer
for (i = 0; i <= TableSize; i = i + 1)
begin
if (i < 16)
char_in = key[ 15 - i ];
master_clock = ~master_clock;
#1;
master_clock = ~master_clock;
#1;
end
// check that the key and RAM were initialized properly
do_key_check = 0;
#1 do_key_check = ~do_key_check;
do_ram_check = 0;
#1 do_ram_check = ~do_ram_check;
#1;
if (! ram_check_rslt )
begin
for (i = 0; i < TableSize; i = i + 1)
begin
$display("design.tbl.Table[%d] = %h", i, design.tbl.Table[i] );
end
end
if (passed)
passed = ram_check_rslt & key_check_rslt;
if (passed)
$display("Test passed");
else
$display("Test failed");
$finish;
end
endmodule // testbench
back to C as a hardware design language