I am trying to build a module that accepts two 16 bit inputs and depending a compare signal, evaluates a certain expression and sends a true (1) value to choice the output if the expression is evaluated as true.
This is my source code:
module comparator(input [15:0] r15_register, sourceone_register , input [1:0] comp_signal, output reg choice);
always #(*)begin
if (comp_signal == 2'b00) begin
//Check if soureceone is greater than r15.
choice = (sourceone_register > r15_register)? 1:0;
end
else if (comp_signal == 2'b01) begin
//Check is sourceone is less than r15.
choice = (sourceone_register <r15_register)? 1:0;
end
else if (comp_signal == 2'b10) begin
//Check if sourceone is equal to r15.
choice = (sourceone_register == r15_register)? 1:0;
end
else
choice <= 0;
end
endmodule
This is my testbench code:
module comparator_fixture();
reg [15:0] r15_register, sourceone_register;
reg [1:0] comp_signal;
wire choice;
comparator utt(.r15_register(r15_register), .sourceone_register(soureone_register), .comp_signal(comp_signal), .choice(choice));
initial begin
#20;
comp_signal = 2'b00;
//Sourceone is greater than r15.
r15_register = 4;
sourceone_register = 6;
//Sourceone is less than r15.
#10;
comp_signal = 2'b01;
r15_register = 6;
sourceone_register = 4;
//Sourceone is equal to r15.
#10;
comp_signal = 2'b10;
r15_register =7;
sourceone_register =7;
#30;
$stop;
end
endmodule
When a comp_signal is given, it drives the output choice to X (an unknown state), and I haven't been able to figure out why. Can someone please offer some advice?
I put your code into Vivado and get errors:
undeclared symbol soureone_register, assumed default net type wire ...
unexpected EOF
I found your waveform already 'weird' as choice was zero while nothing else had been given a value yet. So whatever you used to produce that waveform, it can't be the code you showed.
After I fixed the errors choice is no longer X.
Found my error, in my fixture there was an error in how I spelled "source" during the instantiation. I have included a waveform of the run after I fixed my spelling error.
Here is the waveform with the correct output of "choice".
Related
I have a conceptual question about FSM's and whether or not the following code is a true FSM. This is for my own curiosity and understanding about the subject. When I wrote this code, I was under the impression that this was an FSM, but now I am not so sure. According to a lot of reading I have done, a TRUE FSM should only consist of a sequential state transition block, followed by either one or two combination blocks to calculate the next state and the output logic.
My current code synthesizes and works on my Basys3 board, so I understand there may be an argument for "if it ain't broke, don't fix it" but it's been bugging me for a while now that I may have an incorrect understanding about how to write an FSM in HDL.
I have tried at least 4 or 5 different ways to rewrite my code using the format mentioned above, but I can't seem to get it without inferring latches, mainly due to the use of a counter, and the fact that pckd_bcd needs to remember its previous value.
Could somebody please explain to me either why this algorithm isn't fit for a true FSM, why it is fit for a true FSM and where my misunderstanding is, or how to rewrite this into the format mentioned above.
module double_dabble #
(
parameter NUM_BITS = 8
)
(
input wire i_clk,
input wire i_rst,
input wire [NUM_BITS-1:0] i_binary,
output wire [15:0] o_pckd_bcd
);
localparam s_IDLE = 3'b000;
localparam s_SHIFT = 3'b001;
localparam s_CHECK = 3'b010;
localparam s_ADD = 3'b011;
localparam s_DONE = 3'b100;
reg [2:0] state;
reg [NUM_BITS-1:0] bin;
reg [3:0] count;
reg [15:0] pckd_bcd;
reg [NUM_BITS-1:0] input_reg;
reg [15:0] output_reg;
assign o_pckd_bcd = output_reg;
always #(posedge i_clk)
begin
if(i_rst)
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
output_reg <= 0;
input_reg <= 0;
end
else
begin
input_reg <= i_binary;
state <= s_IDLE;
// FSM
case(state)
s_IDLE :
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
if (input_reg!=i_binary)
begin
bin <= i_binary;
state <= s_SHIFT;
end
end
s_SHIFT :
begin
state <= s_CHECK;
bin <= bin<<1;
count <= count+1;
pckd_bcd <= pckd_bcd<<1;
pckd_bcd[0] <= bin[NUM_BITS-1];
end
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
s_ADD :
begin
state <= s_SHIFT;
pckd_bcd[15:12] <= add_three(pckd_bcd[15:12]);
pckd_bcd[11:8] <= add_three(pckd_bcd[11:8]);
pckd_bcd[7:4] <= add_three(pckd_bcd[7:4]);
pckd_bcd[3:0] <= add_three(pckd_bcd[3:0]);
end
s_DONE :
begin
state <= s_IDLE;
output_reg <= pckd_bcd;
end
endcase
end
end
function [3:0] add_three;
input [3:0] bcd;
if (bcd > 4)
add_three = bcd +3;
else
add_three = bcd;
endfunction
endmodule
In general, your code looks like it implements an FSM. You have evidence that the design is working as desired on your board.
The coding style you have chosen (one always block) is a valid Verilog approach. Another common FSM coding style involves two always blocks: one sequential and one combinational. See here for an example. It is not mandatory for an FSM to use two always blocks in Verilog.
One thing that I do notice in your code is that you are making multiple nonblocking assignments to the state signal at the same time. That is unusual.
For example, right before the case statement, you have:
state <= s_IDLE;
Then, in the IDLE case-item, you have the same code:
state <= s_IDLE;
I recommend trying to clean that up by adding a default to the case statement. A default is also a good coding practice when you have some undefined states, as in your FSM. You have only defined 5 of the 8 possible states (state is a 3-bit register).
Another example of multiple nonblocking assignments is:
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
That would be better coded as:
s_CHECK :
begin
state <= (count>=NUM_BITS) ? s_DONE : s_ADD;
end
Following recommended coding practices yields more predictable simulation and synthesis results.
Im working on a project and after chasing down a bug i narrowed it down to it being caused by an Always block that doesnt trigger correctly.
module Counter(start,clk_len,done,clk,reset);
input [4:0] clk_len;
input clk,start,reset;
output done;
reg [4:0] cntr_var = 0; reg start_val = 0;
assign done = !start_val;
reg test = 0;
always #(reset){cntr_var,start_val} = 2'b0;
always #(posedge start) begin
start_val = start;
end
always #((done and cntr_var == clk_len)) begin // <=== This is the source of the problem
cntr_var = 0;
start_val = 0;
test = 1;
end
always #(clk and !reset) begin
if (start_val == 1 && cntr_var != clk_len)
cntr_var = cntr_var + 1;
end
endmodule
One of the always blocks is supposed to trigger when done AND (cntr_var == clk_len).
I tried using both && and and as the logic operator.
Why isnt this working?
Your first big problem is #(expression) means "wait until the expression has a value change". That change could be from 1➩0 or 0➩1. Typically one only uses always #(posedge clk) for synchronous logic, or always #(*) for combinational logic. (always_comb in SystemVerilog)
Your other problem is you should only be making assignments to a particular variable from one, and only one always block.
I'm trying to test if a wire(s) is on or not to signify if there is an error/overflow in my alu code. Given this code:
output reg[3:0]x; // line 149
output wire error;
output wire overflow;
always #* begin
if(error || overflow) begin
assign x = 4'b1111; // line 155
assign error = ~error;
assign overflow = ~overflow;
end else begin
assign x = opcode;
end
end
I get following error messages:
uut is my instantiation unit in my testbench called main
The code in the example has several issues.
1) you tried to use 'procedural assignments' which is an advanced verilog topic. In other words assign statement inside of an always block. This is not synthesizable, can only be used on reg types, and is there in verilog for very special cases. Do not use it.
You error messages coming from the fact that error and overflow are declared as wire.
2) you are trying to assign inverted version of a value to itself in a non-clocked logic. It will not behave the way you expect. Depending on usage it can either not toggle or will cause an infinite zero-delay loop, or in your case it could just generate a glitch.
So, potentially, your code should look something like the following:
input wire clk; // << you need clock
output reg[3:0]x; // line 149
output wire error;
output wire overflow;
reg error_reg, overflow_reg;
always #(posedge clk) begin
if(error || overflow) begin
x <= 4'b1111; // line 155
error_reg <= ~error;
overflow_reg <= ~overflow;
end else begin
x <= opcode;
end
assign error = error_reg;
assign overflow = overflow_reg;
end
Your using the assign incorrectly. That can be used outside of a always process, but not inside of one.
Also, the type wire, is required for an assign
wire [3:0] x;
assign x = 4'b1111;
Inside the always process, remove the assign statement and just say
reg [3:0] x; // Note that this is assigned as a reg now
always #* begin
if(blah) begin
x = 4'b1111;
end else begin
x = opcode;
end
end
I'm newbie to a verilog.
I did a lot of research, and finally wrote this code, but it seems to not work.
Can anyone fix it for me?
module comparator();
reg[3:0] a, b;
wire[1:0] equal, lower, greater;
if (a<b) begin
equal = 0;
lower = 1;
greater = 0;
end
else if (a==b) begin
equal = 1;
lower = 0;
greater = 0;
end
else begin
equal = 0;
lower = 0;
greater = 1;
end;
initial begin
$monitor($time,
"a=%b, b=%b, greater=%b, equals=%b, lower=%b",
a, b, greater, equal, lower);
a=9; b=10;
#100 $display ("\n", $time, "\n");
end
endmodule
Behavioural procedures must be enclosed within an always block, like this:
Also, your module needs inputs and outputs. A more correct version would be like this:
module comparator (
input wire [3:0] a,
input wire [3:0] b,
output reg equal,
output reg lower,
output reg greater
);
always #* begin
if (a<b) begin
equal = 0;
lower = 1;
greater = 0;
end
else if (a==b) begin
equal = 1;
lower = 0;
greater = 0;
end
else begin
equal = 0;
lower = 0;
greater = 1;
end
end
endmodule
I suggest reading some tutorial about behavioral modelling with Verilog, because you missed a lot of points:
How to correctly define inputs and outputs in a module
What things can be wires and what things should be regs
The use of always #* to model combinational logic
And most important: how to write a test bench. Test benches are written as module with no inputs and outputs) that instantiates your UUT (unit under test), provides inputs, read outputs and check whether they are valid.
module testcomp;
reg [3:0] a, b;
wire eq, lw, gr;
comparator uut (
.a(a),
.b(b),
.equal(eq),
.lower(lw),
.greater(gr)
);
initial begin
a = 0;
repeat (16) begin
b = 0;
repeat (16) begin
#10;
$display ("TESTING %d and %d yields eq=%d lw=%d gr=%d", a, b, eq, lw, gr);
if (a==b && eq!=1'b1 && gr!=1'b0 && lw!=1'b0) begin
$display ("ERROR!");
$finish;
end
if (a>b && eq!=1'b0 && gr!=1'b1 && lw!=1'b0) begin
$display ("ERROR!");
$finish;
end
if (a<b && eq!=1'b1 && gr!=1'b0 && lw!=1'b1) begin
$display ("ERROR!");
$finish;
end
b = b + 1;
end
a = a + 1;
end
$display ("PASSED!");
$finish;
end
endmodule
You can play with this example at EDAPlayGround using this link:
http://www.edaplayground.com/x/CPq
Without always block:
module comparator (
input wire [3:0] a,
input wire [3:0] b,
output reg equal,
output reg lower,
output reg greater
);
assign equal = (a===b);
assign lower = (a<b)?1'b1:1'b0;
assign greater = (a>b)1'b1:1'b0;
end
Be careful, you need to consider 'X' and 'Z', use "===" instead of "=="
Can you tell me why this simple verilog program doesn't print 4 as I want?
primitive confrontatore(output z, input x, input y);
table
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive
comparatore :
module comparatore (r, x, y);
output wire r;
input wire [21:0]x;
input wire [21:0]y;
wire [21:0]z;
genvar i;
generate
for(i=0; i<22; i=i+1)
begin
confrontatore t(z[i],x[i],y[i]);
end
endgenerate
assign r = & z;
endmodule
commutatore :
module commutatore (uscita_commutatore, alpha);
output wire [2:0]uscita_commutatore;
input wire alpha;
reg [2:0]temp;
initial
begin
case (alpha)
1'b0 : assign temp = 3;
1'b1 : assign temp = 4;
endcase
end
assign uscita_commutatore = temp;
endmodule
prova:
module prova();
reg [21:0]in1;
reg [21:0]in2;
wire [2:0]uscita;
wire uscita_comparatore;
comparatore c(uscita_comparatore, in1, in2);
commutatore C(uscita, uscita_comparatore);
initial
begin
in1 = 14;
$dumpfile("prova.vcd");
$dumpvars;
$monitor("\n in1 %d in2 %d -> uscita %d uscita_comparatore %d \n", in1, in2, uscita, uscita_comparatore);
#25 in2 = 14;
#100 $finish;
end
endmodule
The issue is in commutatore. You are using initial, which means the procedural block is only executed at time 0. At time 0, the input alpha is 1'bx, meaning temp is not assigned to anything. Instead of initial, use always #* which will execute the procedural block every time alpha changes.
Generally you should not assign statements in procedural blocks. It is legal Verilog however it is often the source of design bugs and synthesis support is limited.
always #*
begin
case (alpha)
1'b0 : temp = 3;
1'b1 : temp = 4;
default: temp = 3'bx; // <-- optional : to catch known to unknown transitions
endcase
end
The reason you are not getting 4 as you expect for an output is because your commutatore uses an initial block with assign statements in it when you wanted an always #* block to perform the combinational logic to get temp. initial blocks only fire once at the beginning of a simulation, while you want continuous assignment to act as combinational logic. Also, the assign statements in the block are not needed, they only make the simulation behave improperly for your purposes (typically, you will never need to use assign inside another block (initial,always,etc) as this has another meaning than simply set x to y.
For example, you really want something like this:
always #(*) begin
case (alpha)
1'b0: temp = 3'd3;
1'b1: temp = 3'd4;
endcase
end
Also, Verilog already has a build XNOR primative so your confrontatore is not needed, you can use xnor instead.