illegal referance to net data in my inout datatype - verilog

I am new to verilog and I am writing a code in verilog for creating a memory block capable to read and write data. it has the following code
I tried all things written in some of the answers of similar type of questions but still I am getting an error.
module memory( wr_n , rst_n ,data ,clk ,add , en);
input wire wr_n;
input wire rst_n;
input wire clk;
input wire en;
parameter size = 255;
parameter n = 7;
inout wire [n:0] data;
input wire [n:0] add;
reg [n:0] mem [size:0];
integer i;
always #( posedge clk , negedge rst_n)
begin
if(!rst_n)
begin
for( i=0; i<=size; i=i+1 )
begin
mem[i] <= 8'hff;
end
end
else
begin
if(en)
begin
if(!wr_n) //read
data <= mem[add];
else //write
mem[add] <= data;
end
else
data = 8'h z;
end
end
endmodule
here when I use continuous assignment before data I get an error like
"LHS in procedural assignment may not be a net:data"
even if I have declared it as wire.
and yeah in my test bench I have declared data as reg type because when I declare it as net it shows again the
"Illegal reference to net error".
I am not able to fix it since long time..please help me out.

The inout port 'data' is of type wire. So, it cannot be used on the left hand side of the <= expression in a procedural block (always block and initial block).
So we should use continuous assignment statements like
assign data = (wr_n == 0)? mem[add]:n{1'bz};
The same holds true when we are driving any values on the inout port form the test bench. The signal connecting to the inout port from the test bench must be of type wire. And hence it should also be written using continuous assignment statements.
assign testbench_inout_signal = (wr_n == 0)? value_to_be_written :n{1'bz};

There is a better way of using an inout port, it should be isolated from the logic to avoid conflicts while reading and writing, remember whenever you use inout ports make sure the points mentioned in the link are satisfied.
One such solution is declare a temporary variable for reading and writing and
by using continuous assignment statement assign values to bidirectional port.
Following snippet will give you some more clearance of how the error can be avoided
reg [n:0] temp; // declare a variable and try to read and write with this variable
if(!wr_n) //read
temp <= mem[add];
else //write
mem[add] <= temp;
assign data = (wr_n==0)? temp : {n{1'bz}};
Remove the else part having data = 8'h z; there cannot be two else for single if statement as per LRM.

Related

How can I use display or monitor in verilog to check a register

I have 2 Modules. One is Register_File_Rf which is a file of 32 Registers I have created. I want to be able to see what every single register is storing.
Can I do this with $display or $monitor somehow?
Where these should be? In actual code or in Testbench, and how do I get the value in testbench when the stored Data is neither input or output?
module Register(
input Clk,
input [31:0] Data,
input WE,
output reg[31:0] Dout
);
reg [31:0] stored;
// With every Positive Edge of the Clock
always #(posedge Clk)begin
// If Write is Enabled we store the new Data
if (WE)begin
stored <= Data;
Dout <= stored;
end else
Dout <= stored;
end
module Register_File_RF(
input [4:0] Adr1,
input [4:0] Adr2,
input [4:0] Awr,
output reg[31:0] Dout1,
output reg[31:0] Dout2,
input [31:0] Din,
input WrEn,
input Clk
);
integer j;
genvar i;
wire [31:0]Temp_Dout[31:0];
reg W_E [31:0];
// Writing only in the first time R0 Register with 0
initial begin
W_E[0] = 1;
end
// Creating the R0 Register
Register register (.Clk(Clk),.WE(W_E[0]),.Data(0),.Dout(Temp_Dout[0]));
// Creating 30 Registers
for(i = 1; i < 32; i = i + 1)begin:loop
Register register (.Clk(Clk),.WE(W_E[i]),.Data(Din),.Dout(Temp_Dout[i]));
end:loop
// Assigning to Dout1 and Dout2 the Data from a spesific register
always #(Adr1, Adr2) begin
Dout1 = Temp_Dout[Adr1];
Dout2 = Temp_Dout[Adr2];
end
// Wrting Data to a specific register
always #(posedge Clk)begin
//Reseting Write Enable of the register to 0
for (j = 0; j < 32; j = j + 1)begin:loop2
W_E[j] = 0;
end:loop2
if(WrEn)begin
W_E[Awr] = WrEn;
end
end
endmodule
Yes, you can do this with either $display or $monitor.
Typically, $monitor would be called inside an initial block since it should only be called at one time in your simulation. It automatically displays values whenever one of its argument signals changes value.
Unlike $monitor, $display only displays values when it is called; it must be called whenever you want to display a signal value. It can be called in an initial block, but it is often called in an always block.
Regarding when to use either one, it is up to you to decide what you require.
If you are not planning to synthesize your modules, you could place monitor/display inside your design module directly. However, if you plan to synthesize, it might be better to place them in the testbench.
You can use hierarchical scoping to view internal signals from the testbench module. For example, assume you named the instance of the Register_File_RF module in the testbench as dut:
Register_File_RF dut (
// ports
);
always #(posedge Clk) begin
$display($time, " dout='h%x", dut.register.Dout);
end
initial begin
$monitor($time, " dout='h%x", dut.register.Dout);
end
$monitor will display a value every time Dout changes value, whereas $display will show the value at the posedge of the clock.
If your simulator supports SystemVerilog features, you can also use bind to magically add code to your design modules.

Quartus does not allow using a Generate block in Verilog

Pretty simple problem. Given the following code:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
generate
genvar k;
for(k=0; k<2; k=k+1) begin: m
always #(posedge clk) begin
if(wren[k])
ram[addr[k]] <= dIn[k];
dOut[k] <= ram[addr[k]];
end
end
endgenerate
endmodule
quarus 13.0sp1 gives this error (and its 20 other ill-begotten fraternally equivalent siblings):
Error (10028): Can't resolve multiple constant drivers for net "ram[63][14]" at main.v(42)
But if I manually un-roll the generate loop:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
always #(posedge clk) begin
if(wren[0])
ram[addr[0]] <= dIn[0];
dOut[0] <= ram[addr[0]];
end
always #(posedge clk) begin
if(wren[1])
ram[addr[1]] <= dIn[1];
dOut[1] <= ram[addr[1]];
end
endmodule
It all becomes okay with the analysis & synthesis step.
What's the cure to get the generate loop running?
I think the correct way is in the lines of what it's explained in this question: Using a generate with for loop in verilog
Which would be transferred to your code as this:
module main(
output reg [1:0][DATA_WIDTH-1:0] dOut,
input wire [1:0][DATA_WIDTH-1:0] dIn,
input wire [1:0][ADDR_WIDTH-1:0] addr,
input wire [1:0] wren,
input wire clk
);
parameter DATA_WIDTH = 16;
parameter ADDR_WIDTH = 6;
reg [DATA_WIDTH-1:0] ram [2**ADDR_WIDTH-1:0];
integer k;
always #(posedge clk) begin
for(k=0; k<2; k=k+1) begin:
if(wren[k])
ram[addr[k]] <= dIn[k];
dOut[k] <= ram[addr[k]];
end
end
endmodule
Keeping all accesses to your dual port RAM in one always block is convenient so the synthesizer can safely detect that you are efefctively using a dual port RAM at register ram.
Both the generate loop and unrolled versions should not have passed synthesis. In both cases the same address in ram can be assigned by both always blocks. Worse, if both bits of wren are high with both addresses being the same and data being different, then the result is indeterminable. The Verilog LRM states last assignment on a register wins and always blocks with the same trigger could be evaluated in any order.
Synthesis requires assignments to registers to be deterministic. Two (or more) always blocks having write access to the same bit is illegal because nondeterministic. If the unrolled is synthesizing correctly, then that means there are constants on wren and addr outside of the shown module that make it logically impossible for write conflict; for some reason the generate loop version is not getting the same optimization. Example of constraints that would allow optimization to prevent multi-always block write access:
One wren is hard coded to 0. Therefore only one block has exclusive access
Address have non overlapping sets of possible values. Ex addr[0] can only be even while addr[1] can only be odd, or addr[0] < 2**(ADDR_WIDTH/2) and addr[1] >= 2**(ADDR_WIDTH/2).
Synthesis is okay with dOut being assigned by two always blocks because each block has exclusive write access to its target bits (non overlapping sets of possible address values).
The single always block in mcleod_ideafix answer is the preferred solution. If both bits of wren are high with both addresses being the same, then wren[1] will always win. If wren[0] should have priority, then make the for-loop a count down.

How to write to inout port and read from inout port of the same module?

This is not about actually creating a verilog module with inout ports. There are tons of posts I've found about that.
What I am stuck on is, if I have a blackbox module with an inout port, let's says it's defined like
module blackbox(inout a, in b, in c)
And I want to instantiate it in a different module like
module myModule(input reg inReg, output wire outWire)
blackbox(outWire);
How do I also drive the blackbox with the inReg and have it output on the outWire at different times? I don't know of a way to connect one and disconnect the other. This is obviously oversimplified. What I really have is below, but it's more complicated.
module sram_control(
input wire HCLK,
input wire [20:0] HADDR,
input wire HWRITE,
input wire [1:0] HTRANS,
input wire [7:0] HWDATA,
output reg [7:0] HRDATA
);
parameter IDLE_PHASE = 2'b00;
parameter WRITE_PHASE = 2'b01;
parameter READ_PHASE = 2'b10;
parameter IDLE = 2'b00;
parameter NONSEQ = 2'b10;
parameter READ = 1'b0;
parameter WRITE = 1'b1;
reg current_state, next_state;
wire CE, WE, OE;
reg [20:0] A;
wire [7:0] DQ;
reg [7:0] DQ_tmp1;
wire [7:0] DQ_tmp2;
async the_mem(.CE_b(CE), .WE_b(WE), .OE_b(OE), .A(A), .DQ(DQ));
always #(posedge HCLK) begin
if(current_state == IDLE_PHASE) begin
next_state <= HTRANS == NONSEQ? (HWRITE == WRITE? WRITE_PHASE : READ_PHASE) : IDLE_PHASE;
A <= HADDR;
end
else if(current_state != IDLE_PHASE) begin
if(HTRANS == NONSEQ) begin
if(HWRITE == WRITE) begin
next_state <= WRITE_PHASE;
end
else begin
next_state <= READ_PHASE;
end
end
else next_state <= IDLE_PHASE;
end
// we never get here
else next_state <= IDLE_PHASE;
end
always#(posedge HCLK) begin
if(current_state == READ_PHASE) HRDATA <= DQ;
end
assign CE = current_state != IDLE_PHASE? 1 : 0;
assign WE = current_state != IDLE && HWRITE == WRITE? 1 : 0;
assign OE = current_state != IDLE_PHASE? 1 : 0;
always#(posedge HCLK) current_state <= next_state;
endmodule
What I need is a way to assign HWDATA to the async module when I want to write to it, and I need a way to assign the output of the async module to HRDATA when I want to read from the async.
For all inout ports, you can read the data at any time. But for driving that net, generally tri state buffers are used. The reason for that is the same net may be shared with multiple modules and since the net is on inout type, to remove conflict of multiple driver, the tri state buffers are used.
For the same above image, here is the code.
assign io = t ? i : 1'bz; // To drive the inout net
assign o = io; // To read from inout net
As you say, this isn't a Verilog question, it's a logic design question.
You need to implement a tri-state driver to drive DQ:
assign DQ = WE ? 8'bz : HWDATA;
(assuming WE is 1'b0 when you are doing a write).
In general I would avoid tri-state logic inside an IC/FPGA, because not only is there the obvious problem when more than one driver drives a bus, it is also a problem if nothing drives the bus (some gates get floating inputs). There are also further problems in IC design. However, presumably you have not choice in this case; presumably you did not design module async. (If you did - take out the inout.)

Verilog - Getting immediate response from external memory

I'm trying to write a Verilog module which iterates over elements of an external memory in each cycle. The problem I'm facing right now, is that changing the address of the memory during the cycle will not cause the input data be changed, in that same cycle.i.e: changing the address will not cause the input data to be changed in one cycle.I'll illustrate the problem with some code:
module r(input rst, ..., output reg [MEMORY_ADDR_WIDTH-1:0] addr, input memory_value);
//...
always #(posedge clk) begin
//...
for(addr = 0; addr < MEMORY_SIZE; addr = addr+1) begin
if (memory_value) //...
// PROBLEM: changing addr in this loop doesn't cause memory_value to change
end
end
endmodule
And here is how I instantiate the module
module top;
reg mem[MEMORY_SIZE-1:0];
wire [MEMORY_ADD_WIDTH-1:0] addr;
//...
r r( rst, ..., addr, mem[addr]);
endmodule
I'm using Modelsim to simulate the design. First of all, is this expected behaviour, and if it is what's a common workaround?
for loops in Verilog are used to create several copies of an assignment. The loop is automatically unrolled (which is why it needs constant bounds).
For example
always#(posedge clk)
for (i=1; i<4; i=i+1)
foo[i] <= foo[i-1]*foo[i-1];
is equivalent to
always#(posedge clk) begin
foo[1] <= foo[0]*foo[0];
foo[2] <= foo[1]*foo[1];
foo[3] <= foo[2]*foo[2];
end
So, the code you provided never assigns a value to addr, which is likely why you aren't see any change. (In the same way that i doesn't appear in the second part of my example)
Consider instead splitting these up.:
always#(posedge clk)
addr<=(addr+1)%ADDR_MAX;
always#(*)begin
if (memory_value) // mem[addr]
//...
end

Having trouble with Verilog inout wires

For the record, I'm a complete Verilog newbie. I'm writing a module that uses a few bidirectional buses.
inout wire [KEY_SIZE-1:0] prevKey;
inout wire [TAG_SIZE-1:0] prevTag;
inout wire [KEY_SIZE-1:0] nextKey;
inout wire [TAG_SIZE-1:0] nextTag;
I know how I read things off of the bus, but how do I write something onto it? If I use an assign statement to a reg, will the value of the reg get clobbered when new data comes onto the wire? Is dealing with an inout port worth the hassle, or should I just make an input and and output bus for each?
If I use an assign statement to a reg...
This statement doesn't really make sense, you don't do assignments to regs, you do assignments to wires.
Simple example of driving an inout wire:
inout wire bidir_wire;
reg drive_value;
reg drive_enable;
reg something;
assign bidir_wire = drive_enable ? drive_value : 1'bz;
always #(posedge clk) begin
drive_value <= ... ; //assign a drive value based on some criteria
drive_enable <= ...;
something <= bidir_wire; //do something with the input value
end

Resources