Why is iverilog complaining about my testbench module? - verilog

I'm writing a verilog module for my CompSci class and this module specifically is the data memory module. Structurally and analytically, I'm looking at it and it should work based off of the other files that I have, but I'm not sure why this one specifically is acting up and giving me all x's. Hoping a fresh set of eyes can help find the error I missed. Thanks in advance.
datamem.v:
module datamem(Ina, Inb, enable, readwrite, dataOut, clk, rst);
input wire [31:0] Ina;
input wire [31:0] Inb;
input wire enable;
input wire readwrite;
input wire clk;
input wire rst;
reg [31:0] memory[0:65535];
output reg [31:0] dataOut;
always #(memory[Ina]) begin
dataOut = memory[Ina];
end
always #(posedge clk) begin
if(1'b1 == readwrite) begin
memory[Ina] = Inb;
end
end
endmodule
datamem_tb.v:
module datamem_tb();
reg [31:0] Ina;
reg [31:0] Inb;
reg enable;
reg readwrite;
reg clk;
reg rst;
wire [31:0] dataOut;
datamem DUT (Ina, Inb, enable, readwrite, dataOut, clk, rst);
initial
begin
Ina <= 32'd0;
Inb <= 32'd0;
enable <= 0;
readwrite <= 0;
#20 Ina <= 32'd1234;
#20 Inb <= 32'd1234;
#20 Ina <= 32'd0517;
#20 Inb <= 32'd10259;
end
always #(Ina or Inb)
#1 $display("| Ina = %d | Inb = %d | dataOut = %d |", Ina, Inb, dataOut);
endmodule

A few things as to why you are getting all 'x:
You never run the clock, you need to add something like the following to have the clock toggle:
initial begin
clk = 1'b0;
forever #5 clk = ~clk;
end
You never assert readwrite which is required to write to your memory module (you set it to 0 on line 20 and never change it). Without being written to, memory will retain its original value of 'x for every element
Aside from that, there are a few other issues with your module:
Use implicit sensitive lists (instead of always #(memory[inA]) use always #(*))
Use non-blocking assignment for your memory write (memory[inA] <= inB)
Consider using $monitor instead of $display for your print statements to avoid timing issues, and you only need call it at the beginning of your initial block in your testbench (http://referencedesigner.com/tutorials/verilog/verilog_09.php)
Your rst and enable arent connected to anything.
Another example of a memory unit implementation can be found here:
Data memory unit

Related

Delay a 32-bit signal with N clock cycle in verilog

I am trying to delay a 32-bit signal using shift register. My logic is a single flip flop delay a signal by 1 clk so I use shift register as it is combination of flip flop can someone guide me what is wrong with this code.
module delay_n_cycles (
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out,
parameter N = 5
);
reg [31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= {shift_reg[30:0], data_in};
if (N == 0) begin
data_out <= shift_reg[31];
end else begin
data_out <= shift_reg[N-1];
end
end
endmodule
First of all, your code is syntactically wrong. parameter cannot be declared in a way you provided.
Your shift register is only 32 bit wide. Usually, to delay multi-bit data this way, you need to keep N copies of data in the register, shift them at one end and read at the other. I guess the following should help:
module delay_n_cycles #(parameter N = 5)(
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out
);
reg [N-1:0][31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= (shift_reg << 32) | data_in;
data_out <= shift_reg[N-1];
end
endmodule
This code will work with system verilog because it used packed multi-dimensional arrays.
You need to shift the reg by 32 (width of the data) in packed version.
Here is an example of a testbench:
module tb();
bit clk;
int clkCount;
initial
forever begin
#5 clk = ~clk;
clkCount++;
end
logic [31:0] data_in, data_out;
initial begin
$monitor("%0t (%0d) [%h]: %0d --> %0d", $time, clkCount, ds.shift_reg[4], data_in, ds.data_out);
for(int i = 0; i < 20; i++) begin
#10 data_in = i;
end
$finish;
end
delay_n_cycles ds(data_in, clk, data_out);
endmodule

Verilog Testbench Results not showing desired dataRead?

I have created the following module for Data_Mem:
module Data_Mem(
input clk,
input memWrite,
input [5:0] addr,
input [31:0] writeData,
output [31:0] readData
);
reg [31:0] readData;
reg [31:0] addrSpace [0:63];
integer i;
initial begin
for (i=0;i<64;i=i+1)
addrSpace[i] = 0;
end
always # (*) begin
if (memWrite == 1)
begin
addrSpace[addr] <= writeData;
end
readData <= addrSpace[addr];
end
endmodule
Now, I have written the following testbench to see if I can get values to stay in a specified location or address. The testbench is as follows:
reg [5:0] addr;
reg [31:0] writeData;
reg memWrite, clk;
wire [31:0] readData;
//
Data_Mem datamem_testUnit1(.clk(clk), .memWrite(memWrite), .writeData(writeData), .readData(readData));
initial
begin
#10 a = 6'b001111; writeData = 32'h000A; memWrite = 0;
#10 a = 6'b000001; writeData = 32'h000C; memWrite = 1;
#10 a = 6'b000001;
#10 $finish;
end
endmodule
For the simulation results, I see that its taking in my desired values just fine, but dataRead is just XXXX for the whole time. I have included a second addr 00011 as to see whether this result is because of any sort of overlap while writing, but I do not see the desired "000C" for readData even when the addr is still declared as 000001. Please help!
I have included a screenshot of my simulation results.
It looks like you simply forgot to connect the addr signal in your testbench to the addr port of your Data_Mem module. Try
Data_Mem datamem_testUnit1(.clk(clk), .memWrite(memWrite), .addr(addr), .writeData(writeData), .readData(readData));
Also, your always-block will infer latches. I think you probably want it to be clocked, like this:
always # (posedge clk) begin
This involves having to drive the clk port in your testbench, however.

Unresolved reference to 'memory'

I'm trying to add a mif file in the Test benh and I am getting ERROR's
here i am using the modelsim simulator and i am getting error as
UNRESOLVED REFERENCE TO MEMEORY
Illegal output or inout port connection for port 'dout'.
Error loading design
`timescale 1ns / 1ps
module ESC_tb;
// Internal TB Signal Definition
reg clock;
reg reset;
wire [4:0] pc_out;
wire [7:0] acc_out;
wire [7:0] mdr_out;
// DUT Instantiation
ESC instESC(.clock (clock),
.reset (reset),
.pc_out (pc_out),
.acc_out(acc_out),
.mdr_out(mdr_out)
);
// Initialize block for Clock and Reset
initial
begin : RESET
reset = 0;
#7 reset = 1;
#18 reset = 0;
end
initial
begin : CLOCK
clock = 1;
#5 clock = 0;
forever #(5) clock = ~clock;
end
// Loading Program and Data Memory
initial
begin : MEMLOAD
#5;
**// GETTING ERROR AT THIS POINT**
$readmemh("program.mif", memory);
/66/
$display("Loaded Memory with program.mif file");
end
initial
begin : DUMP_FINISH
$dumpvars;
#1000
$finish(2);
end
endmodule
MEMORY.FILE
module memory (clock, addr, din, we, dout,clear);
// Input/Output Declaration
input clock;
input [4:0] addr;
input [7:0] din;
input we,clear;
output [7:0] dout;
// Signal Type Definition
wire clock;
wire [4:0] addr;
wire [7:0] din;
wire we;
wire [7:0] dout;// Memory Array Declaration of Size 16x256
reg [7:0] mem [0:31];
// Memory Write Operation
always #(posedge clock)
begin
if(we)
mem[addr] <= din;
if(clear)
mem[addr] <= 0;
end
// Memory Read Operation
assign dout = mem[addr];
// End of Module Declaration
endmodule
memory is a module, $readmemh is looking for an array. You need to give the full path from the test bench to mem (within the memory module), or call $readmemh within the memory module.
From TB: $readmemh("program.mif", ESC_tb.instESC./*rest of path*/.mem);
From memory module: initial $readmemh("program.mif", mem);

NgdBuild:605 - logical root block 'test_bench' with type 'test_bench' is unexpanded. Symbol 'test_bench' is not supported in target 'artix7'

error is NgdBuild:605 - logical root block 'test_bench' with type 'test_bench' is
unexpanded. Symbol 'test_bench' is not supported in target 'artix7'. at ISE.
Please let me know why appear this error
module Processor_Top(CLK, Inst, I_addr);
input CLK;
input [31:0] Inst;
output [31:0] I_addr;
reg [31:0] address;
reg [31:0] I_addr;
initial address = 32'h00000000;
always#(posedge CLK)
begin
$display ("%h", address);
$display (" Fetched Instruction: %h", Inst);
address = address + 4;
I_addr = Inst[address];
end
endmodule
2. Instruction Memory
module Instruction_Memory(Address, Data);
input [31:0] Address;
output [31:0] Data;
reg [31:0] mem [0:63];
initial begin
$readmemh("isort.cod",mem);
end
assign Data = mem[Address];
endmodule
3. test_bench.v
module test_bench;
// Inputs
reg CLK;
wire [31:0] Inst;
// Outputs
wire [31:0] I_addr;
// Instantiate the Unit Under Test (UUT)
Processor_Top uut (
.CLK (CLK),
.Inst (Inst),
.I_addr(I_addr)
);
Instruction_Memory im(I_addr, Inst);
initial begin
// Initialize Inputs
CLK = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always #100
begin
CLK<=~CLK;
end
endmodule
It looks fine in EDAPlayground.
I had to comment out the $readmemh("isort.cod",mem); though.
As a style guide though it is more common to write:
always begin
#100 CLK = ~CLK;
end
It is correct to use blocking (=) assignments here. You should be using non-blocking (<=) in your edge triggered processes (always#(posedge CLK)).
To run for 100 cycles you can do some thing like the following, at present you testbench will run forever :
initial begin
CLK = 0;
// Wait 100 ns for global reset to finish
//#(posedge globalreset_n);
#(posedge CLK);
// Add stimulus here
repeat(100) begin
#(posedge CLK);
end
$finish();
end

Simulation output is all zeroes

My code for the design block and the testbench compiles; however, when I simulate, I'm not getting the correct output. Can anyone tell me where I'm going wrong in my code?
Here is the code for testbench:
module testbench;
reg [511:0]FROM_LS;
reg CLK;
reg [63:0]TO_IF_ID;
initial
begin
CLK= 0;
TO_IF_ID[63:0]=63'b0;
FROM_LS[511:480]= 32'b00011_00000_00100_01100_11100_10111_01;
FROM_LS[479:448]=32'b00_11000_00100_01111_11111_00011_10000;
end
always
begin
#10 CLK= ~ CLK;
//FROM_LS[511:448]= ~ FROM_LS[511:448];
$display("FROM_LS= %b", FROM_LS);
$display("TO_IF_ID= %b", TO_IF_ID);
end
endmodule
and here is the code for the design block:
module inst_line_buffer(input wire [511:0]from_LS,
input wire clk,
output reg [63:0]to_if_id);
parameter mem_size=16;
integer k;
reg [31:0] ilb[0:mem_size-1];
initial
begin
for (k = 0; k < mem_size ; k = k + 1)
begin
ilb[k] = 32'b00;
//$display ("ilb= %b",ilb[k]);
end
end
always #(posedge clk)
begin
ilb[0]= from_LS[511:480];
ilb[1]= from_LS[479:448];
ilb[2]= from_LS[447:416];
ilb[3]= from_LS[415:384];
ilb[4]= from_LS[383:352];
ilb[5]= from_LS[351:320];
ilb[6]= from_LS[319:288];
ilb[7]= from_LS[287:256];
ilb[8]= from_LS[255:224];
ilb[9]= from_LS[223:192];
ilb[10]= from_LS[191:160];
ilb[11]= from_LS[159:128];
ilb[12]= from_LS[127:96];
ilb[13]= from_LS[95:64];
ilb[14]= from_LS[63:32];
ilb[15]= from_LS[31:00];
to_if_id [63:32]= ilb[0];
to_if_id [31:0]= ilb[1];
$display("ilb= %b", ilb[1]);
end
endmodule
I'm expecting that the value of TO_IF_ID should be 0001100000001000110011100101110100110000010001111111110001110000, but I'm getting all zeros.
When you run a simulation on your testbench module, TO_IF_ID is always 0 because you only assigned a value to it once at time 0 in your initial block. If you want the value to change, it needs to be driven somehow.
As Andy pointed out in a comment, you probably meant to instantiate the inst_line_buffer module in your testbench. Verilog will not do this magically for you. But then, you should declare TO_IF_ID as a wire instead of a reg and remove it from the initial block.
module testbench;
reg [511:0]FROM_LS;
reg CLK;
wire [63:0]TO_IF_ID;
inst_line_buffer inst_line_buffer (
.from_LS (FROM_LS),
.clk (CLK),
.to_if_id (TO_IF_ID)
);
initial begin
CLK= 0;
FROM_LS[511:480]= 32'b00011_00000_00100_01100_11100_10111_01;
FROM_LS[479:448]=32'b00_11000_00100_01111_11111_00011_10000;
#500 $finish;
end
always
begin
#10 CLK= ~ CLK;
//FROM_LS[511:448]= ~ FROM_LS[511:448];
$display("FROM_LS= %b", FROM_LS);
$display("TO_IF_ID= %b", TO_IF_ID);
end
endmodule

Resources