Design a Binary to Gray Code Converter that converts a 4-bit binary input into its 4-bit Gray code equivalent.
bin2gray4bin_in[3:0]gray_out[3:0]| bin | gray | bin | gray | bin | gray | bin | gray |
|---|---|---|---|---|---|---|---|
| 0000 | 0000 | 0100 | 0110 | 1000 | 1100 | 1100 | 1010 |
| 0001 | 0001 | 0101 | 0111 | 1001 | 1101 | 1101 | 1011 |
| 0010 | 0011 | 0110 | 0101 | 1010 | 1111 | 1110 | 1001 |
| 0011 | 0010 | 0111 | 0100 | 1011 | 1110 | 1111 | 1000 |
Note - Binary to Gray conversion
The most significant bit (MSB) of the Gray code is the same as the MSB of the binary input. Each subsequent bit of the Gray code is obtained by XORing the current bit of the binary input with the previous bit.

. notation: top.u1.u2.signal.Syntax:
module <name> #(parameter ... ) (port list);
// declarations
// functionality
endmoduleinput, output, inout)macromodule is an alias for module (rarely used).module … endmodule.Instantiation:
mod_name inst_name (.port1(sig1), .port2(sig2)); // named mapping
mod_name inst_name (sig1, sig2); // ordered mappingBy order: Ports matched in the order declared.
adder u1 (a, b, sum);⚠️ Risky: Errors occur if order changes.
By name: Ports explicitly named.
adder u1 (.x(a), .y(b), .z(sum));âś… Recommended: Safer against future changes.
input – read-only inside the module.output – driven inside, observed outside.inout – bidirectional (used in buses like I²C, data buses).wire.reg if procedural assignment needed.Example:
module m(input clk, input [7:0] data, output reg q, inout bus);0 → logic zero1 → logic onez/Z → high impedance (tri-stated)x/X → unknown (simulation only!)Hardware reality: Only 0, 1, Z exist. X indicates indeterminate logic (conflict, uninitialized, timing issue) in simulation.
~0 = 1, ~1 = 0~x = x, ~z = xxx1 if odd # of 1’s)x/z → result = xx/z poisons result.x.Syntax:
<type> [msb:lsb] <name>;Example:
wire [7:0] data_bus; // 8-bit wide bus (data_bus[7]..data_bus[0])
reg [15:0] acc; // 16-bit register
[7:0] → descending (bit 7 = MSB, bit 0 = LSB) — most common.[0:7] → ascending (bit 0 = MSB, bit 7 = LSB) — allowed, but less used.⚠️ Gotcha: A vector’s indexing direction matters in part-selects and concatenations.
Access individual bits:
data_bus[0] // LSB
acc[15] // MSBSyntax:
vector[msb:lsb] // fixed part-select
vector[base +: width] // indexed part-select (2001+)
vector[base -: width]Examples:
data_bus[7:4] // upper nibble of 8-bit bus
acc[11:8] // 4 bits from acc
// Indexed part-select (IEEE 1364-2001 & 2005)
acc[3 +: 4] // acc[6:3] (4 bits starting at index 3, ascending)
acc[7 -: 4] // acc[7:4] (4 bits descending from 7)âś… Indexed part-select avoids confusion when ranges flip.
{}Syntax:
{expr1, expr2, expr3}Examples:
wire [3:0] a = 4'b1010;
wire [3:0] b = 4'b1100;
wire [7:0] c;
assign c = {a, b}; // c = 1010_1100{N{expr}} repeats an expression N times.Example:
{4{1'b1}} // 1111 (4-bit all ones)
{2{a}} // {a,a} → duplicates a vectorScalars and vectors can mix:
{a[3:0], 2'b11, b[1]} // concatenates 4+2+1 = 7 bitsIf RHS narrower → zero-filled (if unsigned) or sign-extended (if signed).
reg [3:0] x;
x = 8'hAB; // x = 4'hB (truncated)& | ^ ~ ^~ ~^Example:
assign out = a & b; // AND each bit&a, |a, ^a, ~&a, ~|a, ~^aExample:
wire parity = ^data_bus; // XOR all bits → paritya << n, a >> n (logical shift, fill with zeros).>>> (arithmetic right shift, preserves sign bit for signed values).Example:
reg signed [7:0] s = -8'd8; // 1111_1000
$display("%b", s >>> 2); // 1111_1110 = -2Out-of-range index: Returns x (unknown).
wire [3:0] a = 4'b1010;
$display("%b", a[10]); // x<size>'<base><value><size>: number of bits<base>: b (binary), o (octal), d (decimal), h (hex)<value>: digitsExamples:
4'b1010 // 4-bit binary
8'hFF // 8-bit hex
'd25 // 32-bit decimal (unsized default)4'b1010'hF = 32-bit hex F.d/h/o/b) and digits are case-insensitive._ allowed → 16'b1010_1100_1111_0000.Preferred syntax:
-8'd6 // 8-bit signed decimal -6
4'shF // signed 4-bit hex = -18'd-6 is illegal.'sd) are sign-extended when assigned.12.34, 0.11.2e3, 4.5E-2_ can be used for readability: 236.123_763_e-12