// // 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