0

I have to create a 32 bit ALU in structural verilog with opcodes for AND(000), OR(001), ADD(010), SUB(110), SLT(111), and BEQ(100). I understand how each of these work individually at the gate level I'm just confused on how to use opcodes to get my desired output. For example if it was a high level language I would write something like if opcode == 100 {output = branch}. I apologize if this is a dumb question I'm just new to verilog and many of the answers online either use behavioral verilog or are very confusing.

Image of circuit

FriendFX
  • 2,929
  • 1
  • 34
  • 63
AlexImp
  • 1
  • 3
  • 1
    I do not have expertise in Verilog, but I do know some things about VHDL. In general, an "if" statement indicates a multiplexer. So, take a look here (if you didn't already have): https://www.doulos.com/knowhow/verilog_designers_guide/if_statement/ You can use multiple if-elses or case-statement. – Arkoudinos Nov 20 '16 at 23:18

1 Answers1

0

You can use the same technique you described in Verilog... to use if statements, they have to be in an always block, like so:

always @ (*) begin
  if (operation == 3'b000) begin
    alu_result = and_result;
  end else if (operation == 3'b001) begin
    alu_result = or_result;
  end else if (operation == 3'b010) begin
    alu_result = add_result;
  // ...repeat this pattern for the other operations except BEQ...
  end else begin
    alu_result = beq_result;
  end
end

In this example, the *_result wires are the resulting values from the individual operations. The code will synthesise to a multiplexer that selects between the individual result values (dependent on the operation) and drives the alu_result which is the final ALU output.

Instead of using if statements, for this application it is probably better to use case like in the following:

always @ (*) begin
  case (operation)
    3'b000: alu_result = and_result;
    3'b001: alu_result = or_result;
    3'b010: alu_result = add_result;
    // ...repeat this pattern for the other operations except BEQ...
    default: alu_result = beq_result;
  endcase
end

As you can see, this is a bit more compact and easy to read. If written correctly, both variants should lead to exactly the same multiplexer logic. Note that in both variants, the alu_result needs to be of type reg [31:0] because we're assigning within a always blocks, but there is a way to use wire if you prefer:

alu_result = operation == 3'b000 ? and_result
           : operation == 3'b001 ? or_result
           : operation == 3'b010 ? add_result
           // ...repeat this pattern for the other operations except BEQ...
           : beq_result;

EDIT

The OP indicated that he needs a bit-level, structural multiplexer code.

A very simple multiplexer can be created out of AND, OR and NOT gates. For example, a 2-way multiplexer could be created as follows:

not(select_inv,select);
and(selected_signal_a,signal_a,select_inv);
and(selected_signal_b,signal_b,select);
or(selected_result,selected_signal_a,selected_signal_b);

In this example, select determines which one of the signal_a and signal_b gets through to the final output selected_result.

You can use the same pattern for more than one select bit (hint: you need three) by e.g. stacking multiple multiplexers in series.

FriendFX
  • 2,929
  • 1
  • 34
  • 63
  • Thanks for the response! As I said, I'm quite new to verilog and not really too sure of the difference between structural and behavioral and I was under the impression that the if statements and always statements were behavioral and not structural. – AlexImp Nov 21 '16 at 00:00
  • @AlexImp You're right, the examples I've given are behavioural Verilog code. Of course, you could use Verilog's built-in primitive gates like `and`, `or` and `xor`, and depending on the type of multiplexer you want you could also use e.g. `bufif1`, but that would be a bit painful without adding another level of hierarchy... how low-level does it need to be? – FriendFX Nov 21 '16 at 00:13
  • It has to be done down to the gate level. From what I've gathered by speaking to my professor and other classmates it should be done with two muxs. A 2x1 mux that handles the Sub op and a 4x1 mux that handles everything else. I've added an image to explain my question in better detail. – AlexImp Nov 21 '16 at 00:27
  • @AlexImp I have added a simple, structural 2-way mux to my answer... let me know if that helps. – FriendFX Nov 21 '16 at 00:48
  • Sorry for the late response. This helps with understanding how the mux works, but I'm still confused as to how the 0 or 1 in the 2x1 mux becomes a part of the rest of the opcode. My plan is if I enter a 1 in the 2x1 mux labeled sub then it negates the b value, however I don't understand how that 1 becomes part of the overall opcode for sub which would be 110. – AlexImp Nov 21 '16 at 14:21
  • @AlexImp Just see the 0 or 1 of the `select` signal as one of your opcode bits. The 2x1 mux selects between two inputs `signal_a` and `signal_b`, so if you make those two signals be the outputs of two more 2x1 muxes, you have 1) a second opcode bit and 2) four possible inputs (the `signal_a` and `signal_b` of both muxes before the original mux). Note that my approach so far has nothing to do with manipulating the `a` and `b` values. Looking at the opcodes however, you can see that the SUB operation has the same value as ADD except one bit, i.e. the one that you want to feed into the SUB mux. – FriendFX Nov 21 '16 at 23:03