iverilog testbench module with outputs - verilog

I'm trying to make a testbench to simulate a working top level module (and child module) however I can't get iverilog to handle the output of top correctly (LEDS,RS232Rx and RS232Tx are physical pins)
here's my attempt at a testbench
module test();
initial begin
$dumpfile("test.vcd");
$dumpvars(0,test);
# 1024 $stop;
end
reg clk = 0; always #1 clk = !clk;
//reg rx,tx;
reg [7:0] opl;
top top1 ( .clk(clk), .RS232Rx(rx), .RS232Tx(tx), .LEDS(opl) );
endmodule
I'm seeing error like this
iverilog -o test-design testbench.v top.v
top.v:47: error: LEDS is not a valid l-value in test.top1.
top.v:8: : LEDS is declared here as wire.
testbench.v:10: error: reg opl; cannot be driven by primitives or continuous assignment.
testbench.v:10: error: Output port expression must support continuous assignment.
testbench.v:10: : Port 4 (LEDS) of top is connected to opl
3 error(s) during elaboration.
I've tried alsorts of things but with not much in the way of an illuminating or different error message, the best LEDS as a testbench output, showing only an error in top.v which is working... I see very similar errors with rx,tx but commented them out to make a shorter output...
just to reiterate top.v does, not only synthesize but behaves exactly as expected on actual hardware

Turns out that despite my top level design was able to output to a wire, iverilog wasn't happy to do this,
adding
reg [7:0] leds;
assign LEDS=leds;
allows my top level design to work on hardware (as before), but also iverilog (icarus) now seems able to deal with it...

Related

How do I load an FPGA's Registers with Data?

Note this question is not for when I am simulating. I have found numerous resources as to how to use readmemh which does not solve my problem. What I am trying to do is load the RAM for a processor that I designed with the program data. I believe that the FPGA is not getting any of the program data, just the HDL description of the processor.
I tried using Verilog's readmemh function, which I now realize is only useful for simulation. I have also tried using the /* synthesis ram_init_file = "file.mif" */; instruction (?). Either way, there was no difference in how the device worked. I simulated all these cases in ModelSim so I know the design works. I just am stumped as to how I can preload the data.
The answer is going to be tool specific because the initial blocks are, in general, not synthezisable. If you can do it, it is just because the tool has a specific template that is matched with your initial block. Initializing a memory is one of these special cases, where the 'initial' block is discarded from your logic but it is used to generate the initialization data passed along the bitstream.
From the Intel Quartus documentation we can see that there are slightly differences on the actual implementation of the two kinds of memories, dedicated RAM and MLABs, however the general idea is to use an initial block:
module ram_with_init(
output reg [7:0] q,
input [7:0] d,
input [4:0] write_address, read_address,
input we, clk
);
reg [7:0] mem [0:31];
integer i;
// Init the memory with these values
initial begin
for (i = 0; i < 32; i = i + 1)
mem[i] = i[7:0];
end
always # (posedge clk) begin
if (we)
mem[write_address] <= d;
q <= mem[read_address];
end
endmodule
Or, for the quartus pro, you can use readmemh, readmemb:
reg [7:0] ram[0:15];
initial
begin
$readmemb("ram.txt", ram);
end
I suggest you look at the documentation linked as the most updated reference.

Calling a Module in Verilog

I just started learning hardware programming using Verilog, and I feel lost because I can't understand what errors mean.
Here, I am calling the module reg31
module nbit_register(input clk, input [31:0]in, input reset, input L,
input load, input shift, output reg[31:0] out);
always#(*)begin
if(load==1)
reg32 add(clk, in, reset,L, out);
else
out={ in[30:0],1'b0};
end
endmodule
But, I get this error:
error: syntax error near "reg32"
This is what the module looks like
module reg32(
input clk,
input [31:0] in,
input rst,
input L,
output [31:0] out
);
Can someone point out the mistake here?
Because you want to "select" and make module reg32 "work" in a if branch.
Imaging a cell phone PCB board. The speaker unit is just out there, even if it's in silent mode. So instantiate reg32 separately, then use your own logic to deal with the nets connected to reg32.
wire [31:0] add_out;
reg32 add(clk, in, reset,L, add_out); // here the 4 inputs are connected to top inputs
// directly. but if you want, you can use 'load'
// to control them similar to the code below.
always#(*)begin
if(load==1)
out = add_out;
else
out = { in[30:0],1'b0};
end
If you're mainly working on software, you need to be familiar to thinking in a "hardware" way.

Drive internal signals in verilog from system verilog testbench

How can you drive internal signals of a DUT verilog code from testbench?
Consider this following example:
module dut(input bit clk);
logic [7:0] data;
endmodule : dut
module top;
bit clk;
dut dut1(.*);
assign dut.data = '0; // this doesn't work.
endmodule
Cross module references do work. The catch, though, is that any signal in the DUT will already be driven. You need to override that driver. Force and release are the usual way of doing this but you can also just use a stronger driver strength.
The default drive strength is "Strong" so the only thing stronger is "supply".
For your example:
assign (supply0, supply1) data = '0;
Strictly speaking, the supply1 is unnecessary as you are only driving zero. However, it eliminates the surprise you might get if you ever need to change your code to drive '1'.

In verilog I have an error that I can't get past

module data_path(
input clk,
input rst,
input inc_pc,
input load_mar,
input load_mbr,
input load_ir,
input r_w,
input [7:0] data_in,
input load_ac,
input mux_sel,
output [7:0] ir_out);
reg [3:0]var;
reg [2:0]opcode;
wire [3:0] w1,w2,w6;
wire [7:0] w3,w4,w5;
pc pc1(.rst(rst),.clk(clk),.inc_pc(inc_pc),.pc_out(w1));
register1 mar(.rst(rst),.clk(clk),.load(load_mar),.in(w1),.out(w2));
memory memory1(.add_in(w2),.data_in(data_in),.data_out(w3),.r_w(r_w));
register2 mbr(.rst(rst),.clk(clk),.load(load_mbr),.in(w3),.out(w4));
register1 ir(.rst(rst),.clk(clk),.load(load_ir),.in(w4),.out(w5));
assign opcode=w4[7:5];
if(opcode==3'b000)
register1 ac(.rst(rst),.clk(clk),.load(load_ac),.in(w4[4:0]),.out(w6));
else
if(opcode==3'b001)
begin
assign var=w6+w4[4:0];
register1 ac(.rst(rst),.clk(clk),.load(load_ac),.in(var),.out(w6));
end
endmodule
Getting error:
data_path.v line 52 expecting 'endmodule', found 'if'
if usually used in the always or initial block (Procedural Blocks; so you can't check opcode with if outside of procedural block. Try to move if inside always # (posedge clk).
You also should move register1 ac(.rst(rst),.clk(clk),.load(load_ac),.in(w4[4:0]),.out(w6)); instantiation outside of if, because you describe hardware and there is no Conditional instantiation of verilog modules
If 'register1' is another Verilog module, this logic will not work. In your code, you are using the output of a Verilog module (something that is not known at static-run time but that instead my change every clock cycle) to determine which of two instances to instantiate.
Instances will exist from the start of run time, and cannot be brought in and out of existence every clock cycle. Instead, you will have to create both instances of 'register1 ac' as two separate instances (with different names, and with their outputs named differently). And then use a mux (multiplexor) to select between the two output busses depending on the value of 'opcode'.
Both prior answers correctly capture some information. You're trying to mux an input to register1 based on the opcode. A little weirdness in that you're sending in either 4b or 5b based on the if-else. I'll let it slide and assume 5b without sign extension for now. Also your output is 4b.
One other thing. Overflow in the opcode 3'b001 add (which doesn't add up in your assign) - how would one add 4b(w6) + 5b(w4[4:0]) into 4b (var) reliably?
Here's the (untested, caution) code revision (snippet of your code above).
Declare a wire that you mux per the opcode.
wire [7:0] tmpin;
Now correctly write the always to capture the behavior
always #(*) begin
if(opcode==3'b000) tmpin = {3'b0,w4[4:0]};
elsif (opcode == 3'b001) tmpin = {4'b0,w6} + w4;
end
Then you just follow with the muxed variable into a concurrent statement - the register declaration.
register1 ac(.rst(rst),.clk(clk),.load(load_ac),.in(tmpin[4:0]),.out(w6));
Have fun!

Better way of coding a RAM in Verilog

Which code is better in writing a RAM?
assigning data_out inside always block:
module memory(
output reg [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always #(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
data_out <= memory[address];
end
endmodule
assigning data_out using assign statement:
module memory(
output [7:0] data_out,
input [7:0] address,
input [7:0] data_in,
input write_enable,
input clk
);
reg [7:0] memory [0:255];
always #(posedge clk) begin
if (write_enable) begin
memory[address] <= data_in;
end
end
assign data_out = memory[address];
endmodule
Any recommendations?
It depends on your requirements.
This registers your memory output. If you are synthesizing this to gates, you will have 8 more flip-flops than in case 2. That means you use a little more area. It also means your output will have less propagation delay relative to the clock than case 2. Furthermore, the output data will not be available until the next clock cycle.
Your output data will be available within the same clock cycle as it was written, albeit with longer propagation delay relative to the clock.
You need to decide which to use based on your requirements.
A third option is to use a generated RAM, which is a hard macro. This should have area, power and possibly timing advantages over both case 1 and 2.
to add to toolic's answer - if you use the asynchronous read method (case 2), it won't map to a RAM block in an FPGA, as the RAM blocks in all the major architectures I'm aware of have a synchronous read.
Both forms are valid, depending on the type of pipelining you want. I always recommend following the Xilinx RAM coding guidelines -- it's a good way to ensure that the code synthesizes into proper FGPA constructs.
For example, your example 1 would synthesize into into Xilinx BRAM (i.e., dedicated Block Ram), since it is synchronous read, and your example 2 would synthesize into Xilinx Distributed Ram (since it is asynchronous read).
See the coding guidelines in Xilinx document UG901 (Vivado Design Suite User Guide), in the RAM HDL Coding Techniques section. It also has a good description of the difference between synchronous read and asynchronous read for RAMs.
In the second program, there would be compilation error as we can not 'Assign' a value to 'Reg'.
It will give an error saying: 'Register is illegal in left-hand side of continuous assignment'

Resources