Big-Endian vs. Little-Endian

Suppose the message is

"The boat"

where the message size in bytes is 8 bytes.

As with the WEP encryption project, the memory representation is little-endian. Therefore, the message would be stored in memory as follows, assuming the message word address starts at location 0:

M[0] = " ehT";
M[1] = "taob";

However, our SHA1 algorithm uses a big-endian representation. This means w[0] and w[1] are as follows:

w[0] <= "The ";
w[1] <= "boat";

Then we pad a 1, then with 0's, so w[2] in hex would be

w[2] <= 32'h80000000; // which is equivalent in 32-bit binary to 10000000000000000000000000000000

and the subsequent words in hex would be

w[3] <= 32'h00000000;
w[4] <= 32'h00000000;
w[13] <= 32'h00000000;

Finally, the message size in bits is padded to the last two words {w[14], w[15]}. In this example, message size = 8 bytes = 64 bits, we would pad the binary representation of "64" in the end.

You can safely assume that the message size in bits will be less than 232, which means we can do this:

w[14] <= 32'h00000000;
w[15] <= 32'h00000040; // because message size = 64 bits, which is equivalent in 32-bit hexadecimal of 32'h00000040
                       // or 32-bit binary of 32'b00000000000000000000000001000000

One easy way to implement this in Verilog is to specify a changeEndian function as follows:

function [31:0] changeEndian;   //transform data from the memory to big-endian form
    input [31:0] value;
    changeEndian = {value[7:0], value[15:8], value[23:16], value[31:24]};

Then in your Verilog code, you can do something like this:

w[i] <= changeEndian(port_A_data_out);

This will change the memory word M[i] in little-endian to w[j] in big-endian -- e.g., it would for example change " ehT" to "The ".

Then for the last word w[15] in the last message block, we can do this:

w[15] <= message_size << 3; // pad message size in bits

This will convert the message_size in bytes to bits.

Note: The statement

w[i] <= changeEndian(port_A_data_out);

uses a nice trick. It allows us to put a bunch of combinational logic into a function, and then assign this logic using a non-blocking assignment.