Rather than addressing the many problems in your source code, let me just show how I'd implement the module you describe.
First, I wouldn't use a sub-module to build the adder; synthesis tools are perfectly able to create adders from behavioral code. Secondly, an elaborate state machine isn't required; the module can simply produce a final result four clocks after each activation of the start
signal. I've added a done
signal to the module interface to make this explicit.
module seq_mult_4bit (
output [7:0] product,
output done,
input [3:0] a,
input [3:0] b,
input clock,
input start
);
reg [7:0] product;
reg [3:0] multiplicand;
reg [3:0] delay;
wire [4:0] sum = {1'b0, product[7:4]} + {1'b0, multiplicand};
assign done = delay[0];
always @(posedge clock) begin
if (start) begin
delay = 4'b1000;
multiplicand = a;
if (b[0]) begin
product <= {1'b0, a, b[3:1]};
end else begin
product <= {1'b0, 4'b0, b[3:1]};
end
end else begin
delay = {1'b0, delay[3:1]};
if (product[0]) begin
product <= {sum, product[3:1]};
end else begin
product <= {1'b0, product[7:1]};
end
end
end
endmodule
If you really want to use an external module for the adder (which is really the point of your question), simply substitute the wire declaration above with the following block of code:
wire [4:0] sum;
rca_4bit adder (
.sum (sum[3:0]),
.c_out (sum[4]),
.a (multiplicand),
.b (product[7:4]),
.c_in (0)
);
Let me know if you have any specific questions about how this implementation works.
always @(negedge GCLK)
foo<= bar; // foo is equal to bar in this cycle or next?
For simple cases where there is nothing going on elsewhere in your code to cause bar
to change simultaneously with GCLK
, this block says, when a negative-going edge is seen on GCLK, "immediately" change the value of foo
to whatever bar
is at that instant.
"Immediately" means something like one simulation tick after the negative edge arrived.
This means that any other tranisitions that happen on the same negative edge of GCLK and depend on the value of foo
will see the old value of foo
. But foo
will have the new value starting right away until the next negative edge of GCLK.
Edit in reply to comments,
If "any other transitions" see the old value of foo, can we assume that foo is "is available in next clock"?
In the simulator, yes. In real life you need to check propagation delays and setup and hold times to be sure.
what if we put always code with begin...end ? All of them will be immediate ? as: always@(negedge GCLK) begin .. foo<=bar; x<= foo+1; end In this example x will be bar+1 in the same cycle as foo assignment ?
No, as mentioned before, any other tranisitions that happen on the same negative edge of GCLK and depend on the value of foo will see the old value of foo.
If you want the other behavior you can use blocking assignment:
...
foo = bar;
x = foo+1;
...
Modern synthesis tools should be able to compile this correctly but old tools might not be able to. What the modern tool will do is simply translate this to
foo <= bar;
x <= bar+1;
and compile that. Since I learned Verilog before this behavior was reliable I find it less familiar to read the code with blocking assignments.
Can we use blocking assignments for immediate and non-blocking for "delayed" assignments?
I'm not quite clear what you mean by this. What a blocking assignment does (in the simulator) is prevent the next statement from executing until after it is complete. Both types of assignment are immediate, but the blocking assingment causes the next statement to be delayed.
If so, it can be a very useful approach for making small delays in the code
For small delays in simulation you can just use delay events
always @(event) begin
foo <= x;
#5
bar <= foo;
end
For small delays in synthesized code, you'd better be sure the hardware can actually do what you're asking for.
Best Answer
You should probably synthesize your design to be sure, but I expect that your example will result in
Out_Reg
being generated from combinatorial logic. It could more conventionally be expressed asIf you want
Out_Reg
to be the output of a physical register (flip-flop), you could writeBut then, of course, the value of
Out_Reg
is delayed by one clock cycle relative to the state ofstate
. If you need it to be in sync, you would need to duplicate thestate
logic so thatOut_Reg
anticipates what the next state ofstate
will be. You could simplify this by using combinatorial logic to create anext_state
signal:However, you should also consider whether this is necessary. Does your downstream logic really care whether the output of this module is physically sourced from a register or from a combinatorial gate?