Verilog module to read/write a register

memoryverilog

I would like to create a module that can change the value of a register passed to it (+/- 1) using an inout port. I wrote this:

module tune(
    input clk,
    input read,
    input [15:0] x,
    inout [15:0] y,
    input plus,
    input minus
);

reg [15:0] a;
reg [15:0] b;

assign y = read ? a:'bz;

always@(posedge clk) begin
    b<=y;
    a<=x;
    if (plus) b<=b+1;
end

endmodule

When read is HIGH, I expect y to be initialized to the value of x.
When read is LOW, I expect to output the value of b (which can be decremented or incremented by using minus or plus).
Currently however, plus does not do anything, and read toggles y between 0xFFFF and 2 (when I pass 2'd42 to x).

I admit I do not have a good grasp of non-blocking assignments. What should I change to make my code work, or is there a better way to implement the desired behavior?

Best Answer

When read is HIGH, I expect y to be initialized to the value of x.

The only thing your code actually does when read is high is to make y output the value from a. As soon as read goes low again y goes back to being an input (because you assign it the value z).

When read is LOW, I expect to output the value of b (which can be decremented or incremented by using minus or plus).

Since b is not an output, and you never use b to set any other wire or register, it's not clear how you expect that to happen.

Currently however, plus does not do anything

Are you sure? In your code, if plus is high at a rising edge of clk, then b will get the value y+1.

and read toggles y between 0xFFFF and 2

Are you sure the value is 0xFFFF and not 0xXXXX? Because when read is low, this code is not assigning any value at all to y. It sounds like your testbench is applying a pull-up or a weak high value to the bits of y.