4 bit x 4 bit using look up table (rom)
assign P = ROM[(A * B)]; should be assign P = ROM[{A,B}]; The curly brackets ({}) is used to concatenate the bits. The square brackets ([]) are for indexing.

For ROM [(i * k)] = (i * k); you will want ROM [{i[3:0],k[3:0]}] = (i * k);

i and k are integers (equivalent to reg signed [31:0]), so {i,k} would be 64 bits wide with i starting at bit 32. The [3:0] is range slice if the integers that are meaningful for this indexing.

Note: you do not want to redefine i and k as reg [3:0] as this will give you an infinite loop 15 + 1 is 0 for a 4-bit reg and always less than 16.