1. You cannot use a case statement and assign statements directly in the module body; you should use a continuous assignment with a function or a combinational always block, or use a continuous assignment with a ternary operator. Example:
    case (sel) begin
        4'b0000: assign y = a; // Select A
        4'b0001: assign y = b; // Select B
        4'b0010: assign y = c; // Select C
        4'b0011: assign y = d; // Select D
        default: assign y = {WIDTH{1'b0}}; // Default case (optional)
    endcase

should be changed to:

    assign y = (sel == 4'b0000) ? a :
               (sel == 4'b0001) ? b :
               (sel == 4'b0010) ? c :
               (sel == 4'b0011) ? d :
               {WIDTH{1'b0}};
  1. When writing a test case where you are mixing up signed and unsigned numbers. In that case, declare as reg signed foo.
  2. PC should be sliced to only use the bits that are used to address the memory. And the lower 2 bits must be dropped because memory is indexed every 4 bits (word) and not a bit. So we drop them to basically divide the address by 4. To “align” the words.