Verilog HDL error: Illegal left-hand side assignment - verilog

I am learning CPU Design and basic Verilog HDL. I have a processor running in tkgate on Fedora 29 and I have designed a hardware RAM disk. I can't test the RAM but have decided to replace it with an HDL RAM disk. Whenever I try to simulate the circuit, I get the error:
RAM_HDL, line 17: Illegal use of 'w7' in left-hand-side assignment.
Here is my code for the RAM:
module RAM_HDL(RAM, Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
wire [15:0] Data_In;
wire [15:0] Data_Out;
wire [7:0] Address;
wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
Data_Out <= Address;
end
endmodule
The error is on line 17:
Data_Out <= Address;

I believe one of your problems is trying to assign to a wire type in an always block. Try changing the declaration of Data_Out to reg instead of wire. The 2 following examples compiled for me:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input wire [15:0] Data_In;
output reg [15:0] Data_Out;
input wire [7:0] Address;
input wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
Data_Out <= Address;
end
endmodule
note the changes. input and output are declared on the ports. The ram array is not one of the ports and the data_out is a reg.
another option would be to move the assignment of data out outside the always block and keep it as a wire:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input wire [15:0] Data_In;
output wire [15:0] Data_Out;
input wire [7:0] Address;
input wire RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
end
assign Data_Out = Address;
endmodule
the changes are mostly the same. the input output declarations and the ram array is removed from the port list. Data_Out however is now assigned outside the always block so it can stay a wire.

The following code compiles at least:
module RAM_HDL(Data_In, Data_Out, Address, RW);
reg [15:0] RAM [127:0];
input [15:0] Data_In;
output [15:0] Data_Out;
input [7:0] Address;
input RW;
initial
$readmemb("RAM_DATA.BIN", RAM);
always #(*)
begin
if (RW)
RAM[Address] <= Data_In;
end
assign Data_Out = RAM[Address];
endmodule

Related

Why is iverilog complaining about my testbench module?

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

CRC32 code does not work

I just started to work with CRC32.So when I wanted to check the code I wrote and I get xxxxxx as the output.I am not sure if the code is right though
module last_time(input [127:0]finalinput,output [31:0]crcout1
,input clk);
wire [31:0]poly;
assign poly=32'h04c11db7;
reg [7:0]lsb;
reg [3:0]i;
reg [7:0]ans;
reg [31:0]nextcrc;
reg [31:0]newcrc;
reg [31:0]crcout;
reg [7:0] lut [255:0];
always#(posedge clk)
begin
crcout=32'hffffffff;
lsb=finalinput;
for(i=0;i<16;i=i+1)
begin
ans=(8'hff^(lsb));
newcrc = lut[ans];
$readmemh("table.txt",lut); // to fill lut
nextcrc=(newcrc)^(crcout>>8);
lsb=lsb>>8;
end
end
assign crcout1=nextcrc^32'hffffffff;
endmodule
The issue was with the input to the LUT, it should be an integer and not a reg value.
The LUT size was not the correct size
module bit32(input [31:0]msg,input [31:0]crcinitial,output reg[31:0]tableout,output [23:0]crcshifted,
output[31:0]newcrc,output reg [7:0]xor1);
wire [7:0]msglsb;
assign msglsb=msg;
wire [7:0]crclsb;
assign crclsb=crcinitial;
integer k;
reg [31:0]lut[0:255];
initial
begin
assign xor1=(crclsb^msglsb)&8'hff;
assign k=xor1;
assign tableout=lut[xor1];
$readmemh("table.txt",lut);
end
assign crcshifted=crcinitial>>8;
assign newcrc=(tableout^crcshifted)^32'hffffffff;
endmodule

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);

Error: Inconsistent with 'net' object

I'm getting this error when I'm trying to simulate my testbench on ModelSim. I'm just in the early stage of the testbench, and I'm just adding some values to a variable when this error appears.
I have instantiated the topmodule and created the DUT for it in the testbench. Using the instance I'm going in the hierarchy where I get my desired variable that I want to assign a value.
I have googled for an answer to this question and the only thing I have found is that I cannot make a procedural assignment to a wire. The thing is that that the variable in question is an input, not a wire.
The project I'm working on is based on the openRISC 1200 architecture. I could not find any testbench that worked properly, that's why I'm trying to write my own.
Below is the testbench code:
module testbenchOR (
);
reg cmd;
reg rst;
reg clk;
//----------------------TOP-LEVEL--------------------------------------
wire iwb_cyc_o; // cycle valid output
wire [31:0] iwb_adr_o; // address bus outputs
wire iwb_stb_o; // strobe output
wire iwb_we_o; // indicates write transfer
wire [3:0] iwb_sel_o; // byte select outputs
wire [31:0] iwb_dat_o; // output data bus
wire dwb_cyc_o; // cycle valid output
wire [31:0] dwb_adr_o; // address bus outputs
wire dwb_stb_o; // strobe output
wire dwb_we_o; // indicates write transfer
wire [3:0] dwb_sel_o; // byte select outputs
wire [31:0] dwb_dat_o; // output data bus
wire [3:0] dbg_lss_o; // External Load/Store Unit Status
wire [1:0] dbg_is_o; // External Insn Fetch Status
wire [10:0] dbg_wp_o; // Watchpoints Outputs
wire dbg_bp_o; // Breakpoint Output
wire [31:0] dbg_dat_o; // External Data Output
wire dbg_ack_o; // External Data Acknowledge (not WB compatible)
wire [3:0] pm_clksd_o;
wire pm_dc_gate_o;
wire pm_ic_gate_o;
wire pm_dmmu_gate_o;
wire pm_immu_gate_o;
wire pm_tt_gate_o;
wire pm_cpu_gate_o;
wire pm_wakeup_o;
wire pm_lvolt_o;
reg clk_i;
reg rst_i;
reg [1:0] clmode_i; // 00 WB=RISC, 01 WB=RISC/2, 10 N/A, 11 WB=RISC/4
reg [19:0] pic_ints_i;
reg iwb_clk_i; // clock input
reg iwb_rst_i; // reset input
reg iwb_ack_i; // normal termination
reg iwb_err_i; // termination w/ error
reg iwb_rty_i; // termination w/ retry
reg [31:0] iwb_dat_i; // input data bus
reg dwb_clk_i; // clock input
reg dwb_rst_i; // reset input
reg dwb_ack_i; // normal termination
reg dwb_err_i; // termination w/ error
reg dwb_rty_i; // termination w/ retry
reg [31:0] dwb_dat_i; // input data bus
reg dbg_stall_i; // External Stall Input
reg dbg_ewt_i; // External Watchpoint Trigger Input
reg dbg_stb_i; // External Address/Data Strobe
reg dbg_we_i; // External Write Enable
reg [31:0] dbg_adr_i; // External Address Input
reg [31:0] dbg_dat_i; // External Data Input
reg pm_cpustall_i;
or1200_top TOP_LEVEL(
.iwb_cyc_o(iwb_cyc_o),
.iwb_adr_o(iwb_adr_o),
.iwb_stb_o(iwb_stb_o),
.iwb_we_o(iwb_we_o),
.iwb_sel_o(iwb_sel_o),
.iwb_dat_o(iwb_dat_o),
.dwb_cyc_o(dwb_cyc_o),
.dwb_adr_o(dwb_adr_o),
.dwb_stb_o(dwb_stb_o),
.dwb_we_o(dwb_we_o),
.dwb_sel_o(dwb_sel_o),
.dwb_dat_o(dwb_dat_o),
.dbg_lss_o(dbg_lss_o),
.dbg_is_o(dbg_is_o),
.dbg_wp_o(dbg_wp_o),
.dbg_bp_o(dbg_bp_o),
.dbg_dat_o(dbg_dat_o),
.dbg_ack_o(dbg_ack_o),
.pm_clksd_o(pm_clksd_o),
.pm_dc_gate_o(pm_dc_gate_o),
.pm_ic_gate_o(pm_ic_gate_o),
.pm_dmmu_gate_o(pm_dmmu_gate_o),
.pm_immu_gate_o(pm_immu_gate_o),
.pm_tt_gate_o(pm_tt_gate_o),
.pm_cpu_gate_o(pm_cpu_gate_o),
.pm_wakeup_o(pm_wakeup_o),
.pm_lvolt_o(pm_lvolt_o),
.clk_i(clk_i),
.rst_i(rst_i),
.clmode_i(clmode_i),
.pic_ints_i(pic_ints_i),
.iwb_clk_i(iwb_clk_i),
.iwb_rst_i(iwb_rst_i),
.iwb_ack_i(iwb_ack_i),
.iwb_err_i(iwb_err_i),
.iwb_rty_i(iwb_rty_i),
.iwb_dat_i(iwb_dat_i),
.dwb_clk_i(dwb_clk_i),
.dwb_rst_i(dwb_rst_i),
.dwb_ack_i(dwb_ack_i),
.dwb_err_i(dwb_err_i),
.dwb_rty_i(dwb_rty_i),
.dwb_dat_i(dwb_dat_i),
.dbg_stall_i(dbg_stall_i),
.dbg_ewt_i(dbg_ewt_i),
.dbg_stb_i(dbg_stb_i),
.dbg_we_i(dbg_we_i),
.dbg_adr_i(dbg_adr_i),
.dbg_dat_i(dbg_dat_i),
.pm_cpustall_i(pm_cpustall_i)
);
initial begin
$display (" --- Start --- ");
clk =0;
rst <= 1;
repeat (1) # (posedge clk);
rst <= 0;
cmd <= 0;
repeat (10) # (posedge clk);
cmd <= 1;
repeat (10) # (posedge clk);
end
// Clock generator
always #10 clk = ~clk;
initial begin
#(posedge clk)
TOP_LEVEL.or1200_cpu.or1200_rf.rf_a.ce_w = 1'b0; //Chip enable input
end
endmodule
The error is as follows:
This or another usage of 'TOP_LEVEL.or1200_cpu.or1200_rf.rf_a.ce_w'
inconsistent with 'net' object.
UPDATE:
The error can be removed by doing the following:
initial begin
#(posedge clk)
force TOP_LEVEL.or1200_cpu.or1200_rf.rf_a.ce_w = 1'b0; //Chip enable input
#500
release TOP_LEVEL.or1200_cpu.or1200_rf.rf_a.ce_w;
end
You may need to use force for an input/wire:
initial begin
#(posedge clk)
force TOP_LEVEL.or1200_cpu.or1200_rf.rf_a.ce_w = 1'b0; //Chip enable input
end
Keep in mind that force will hold that value until you release the signal. Refer to IEEE Std 1800-2012, section "10.6.2 The force and release procedural statements". Also keep in mind that force/release should be used sparingly.

Data shifting in verilog

I have a number of 32 bit. I need only its first 8 bits. I think I can do this by two methods: one is by shifting the number to 24 bits right and other is by simply assigning the last 8 bits to a variable.
Here is what I am trying to do:
module Data_shiftin(
input reset_n, clk,
input [31:0] data_in,
output [31:0] data_out
);
reg [31:0] data_reg;
reg data_out;
always # (posedge clk)
begin
data_out<=data_in[31:23];
end
endmodule
But I am getting only last bit i.e. 32nd bit of the number. I don't know where I am doing error.
Thanks!
P.S: I am a newbie to this language.
The assignment you have is correct, but you are only getting one bit because you are redeclaring data_out as a single-bit reg. Try changing:
reg data_out
To:
reg[31:0] data_out
A better option though it to use Verilog-2000 style port declarations and place the reg keyword in the port list.
Example:
module Data_shiftin(
input wire reset_n,
input wire clk,
input wire [31:0] data_in,
output reg [31:0] data_out
);
always # (posedge clk)
begin
data_out <= data_in[31:23];
end
endmodule
Note also that your tool may warn you about a width mismatch because you are assigning an 8-bit value to a 32-bit value. To explicitly assign only the lower 8 bits of data_out you should use:
data_out[7:0] <= data_in[31:23]

Resources