problem with flattening an array in verilog - verilog

I tried to flatten an array with numbers into a variable in order to pass it as an input to a module in verilog. But, I get the error:
Port 1 (DATA_IN) of process_data expects 64 bits, got 4096. Pruning
4032 high bits of the expression.
I know that my module process_data in not ready yet and hence it does not work properly, but my problem for now is that the input is a lot more bits than it should.
Do you know how could I fix it?
module process_data(input wire [63:0] DATA_IN , input wire [6:0]AdrR , input wire [6:0]AdrW, input R_W , input Cen, input clk, input reset, output reg [63:0]Reg_Data_Out);
integer i;
reg [63:0]Memory[63:0]; //64 * 64 bit array
initial
begin
i=0;
//++for
repeat (64)
begin
Memory[i]=64'd1; //64 = number of the thesis that the vector has
i=i+1;
end
end
always #(negedge(clk))
//initial AdrR ,AdrW = 0; // 7'b0000_000;
begin
if(Cen == 1'b1) begin // cen = chip enabled
case (R_W)
1'b1:
//++check if not empty
Reg_Data_Out = Memory[AdrR]; // (read) out put memory context
1'b0:
//++check if not full
Memory[AdrW] = DATA_IN; // write input to memory
default:
Reg_Data_Out = 64'bxxxxxxxx;
endcase
end
end
endmodule
module TOP();
reg [63:0] inputdata1 [0:127]; //array
reg [64*64-1:0] flattened_inputdata1;
reg [6:0] AddressR,AddressW;
reg cen,clk, R_W, reset;
wire [63:0] Data_Out;
//pass the numbers
integer count;
initial
begin
count = 0;
while (count < 128) // Execute loop till count is 127. exit at count 128
begin
// every timh that the integer variable count takes must be also passed into reg inputdata1
inputdata1[count] = count;
count = count + 1;
end
end
//flattening
initial
begin
count = 0;
while (count < 128) // Execute loop till count is 127. exit at count 128
begin
flattened_inputdata1[64*count +: 64] = inputdata1[count];
//flattened_inputdata1[(64*count) +63) : (64*count)] = inputdata1[count]; //declare a number is dekadikos
count = count + 1;
end
end
//call module for data I/O
process_data process_data( flattened_inputdata1, AddressR, AddressW, R_W , cen, clk, reset, Data_Out); //reset does not do anything yet
always #10 clk=~clk;
initial
begin
$display("flattenedinputdata1=%d", flattened_inputdata1);
cen=1'b1; //chip enabled
#50
R_W=1'b1; //read
AddressR=7'b0000_000;
#50
//R_W=1'b1; //read
//AddressR=7'b0000_001;
$finish; //#50 $finish;
end
endmodule
edaplayground link

You can see from the declarations that the sizes are different:
input wire [63:0] DATA_IN
and the thing you're passing in to it:
reg [64*64-1:0] flattened_inputdata1;
DATA_IN is 64 bits and flattened_inputdata1 is 4096 bits. So you'll need to change one of them so that the two sizes match.

Related

verilog testbench(with for loop) for 3-8 decoder signal value not updating

I'm new to verilog. I write a 3-8 decoder and a testbench for it. This is 38_decoder_tb.v:
module decoder_38(input [2:0] in, output reg [7:0] out);
always #* begin
case (in) //Switch based on concatenation of control signals
3'b000 : out = 8'b00000001;
3'b001 : out = 8'b00000010;
3'b010 : out = 8'b00000100;
3'b011 : out = 8'b00001000;
3'b100 : out = 8'b00010000;
3'b101 : out = 8'b00100000;
3'b110 : out = 8'b01000000;
3'b111 : out = 8'b10000000;
endcase
end
endmodule
This is 38_decoder_tb.v:
`timescale 1ns / 1ns
module tb_decoder_38;
// decoder_38 Parameters
parameter PERIOD = 20;
// decoder_38 Inputs
reg [2:0] in ;
// decoder_38 Outputs
wire [7:0] out ;
reg clk;
integer i;
initial
begin
clk = 0;
forever #(PERIOD/2) clk=~clk;
end
decoder_38 u_decoder_38 (
.in ( in [2:0] ),
.out ( out [7:0] )
);
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i < 3'd8; i=i+1) begin
in = i;
#PERIOD;
end
end
endmodule
I stimulate the testbench module with ModelSim 10.5. As you can see, the signal just doesn't update. What's the problem? Does it have something to do with the for loop?
Yes, the issue is with the loop.
Your problem is in definition of 3'd8. 8 is the same as 1000 in binary presentation and requires 4 bits. Therefore, 3-bits of it (as you requested) yield 000. As a result your loop does not run at all, looking like the following: for (i = 3'd0; i < 0; i++).
Variable i is defined as integer. An integer type is a 4-state data type, 32-bit signed integer. So, rewriting loop as for(i = 0; i < 8; i++) will solve your issues. There is absolutely no need to define sizes for the constants in this loop.
And, to avoid infinite loop, you need to use $finish when appropriate, as suggested in the other answer.
The posted testbench has an infinite loop because of the forever loop with nothing to stop it.
I added a #30 delay to see the last clock of data, and $finish to stop it.
After that the code behaves as expected.
All 4 simulators on EDA Playground show the same.
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i <= 3'd7; i=i+1) begin
in = i;
#PERIOD;
end
//
#30;
$finish;
end
Here is a link playground I put together https://www.edaplayground.com/x/aZYL

1 Second ClkDivider Simulation Not Working

I am trying to create a second clk counter using a 100 MHz clk input, but when I simulate the clk divider, it just shows the output as an X even though the clk input is correct. What could I be doing wrong?
1 second clk divider:
module clkdiv(
input clk,
input [25:0] terminalcount,
output reg clk_div
);
reg [25:0] count;
wire tc;
assign tc = (count == terminalcount);
always # (posedge(clk)) begin
if (tc) count <= 0;
else count <= count + 1;
end
always # (posedge(clk)) begin
if (tc) clk_div = !clk_div;
end
endmodule
Test Bench:
module clockdivTB;
// inputs
reg clk; // make 100 MHz -- T = 10 ns
// outputs
wire newclk;
// second clock -- connect test signals to clkdiv
clkdiv slowclkCUT (
.clk(clk),
.terminalcount(50000000-1), // 1 Hz
.clk_div(newclk)
);
// initialize inputs
initial begin
clk = 0;
// create input clock 100MHz
forever #5 clk = ~clk;
end
endmodule
Result:
The output is X because reg types are initialized to X (unknown). You need to initialize the output to a known value. For simulation purposes, you can set clk_div and count to 0 as follows:
module clkdiv(
input clk,
input [25:0] terminalcount,
output reg clk_div = 0
);
reg [25:0] count = 0;
However, if you want to synthesize your logic, you likely need to add a reset input. You can drive the input from your testbench.
module clkdiv(
input reset,
input clk,
input [25:0] terminalcount,
output reg clk_div
);
reg [25:0] count;
wire tc;
assign tc = (count == terminalcount);
always # (posedge(clk)) begin
if (reset) count <= 0;
else if (tc) count <= 0;
else count <= count + 1;
end
always # (posedge(clk)) begin
if (reset) clk_div <= 0;
else if (tc) clk_div <= !clk_div;
end
endmodule

verilog code for ram

I am trying to simulate the following code for an asynchronous ram in verilog. But dout remains xxxx all the time.
The first time I tried the code dout was equal to din for the time when write signal was 1.After that it was all xxxx.Can anyone tell me the problem?It'd be great if you could suggest a better code.
module ram(cs,wr,addr,din,dout);
parameter adds = 10, wsize =16, memsize =1024;
input cs,wr;
input [adds-1:0] addr;
input [wsize-1 : 0]din;
output [wsize-1:0]dout;
reg [wsize-1:0] mem [memsize-1:0];
assign dout = mem[addr];
always #(cs or wr)
begin
if(wr) mem[addr]= din;
end
endmodule
The test bench for the above code is :
module ramtest;
// Inputs
reg cs;
reg wr;
reg [9:0] addr;
reg [15:0] din;
// Outputs
wire [15:0] dout;
integer k,myseed;
// Instantiate the Unit Under Test (UUT)
ram uut (
.cs(cs),
.wr(wr),
.addr(addr),
.din(din),
.dout(dout)
);
initial begin
for(k = 0; k<=1023; k = k+1)
begin
din = k % 256; wr = 1; cs= 1;addr= k ;
end
repeat(20)
begin
#2 addr = $random(myseed) % 1024 ;
wr = 0; cs =1;
$display("Address = %5d, data = %4d",addr,dout);
end
end
initial myseed = 35 ;
endmodule
Several errors:
Your wr and cs do not change so the always #( cs or wr) is only
entered once for write and once for read.
Your 'write' code in
the testbench for(k = 0; k<=1023; k = k+1) does not have a delay.
So there is no time for the write to actually happen.
However the biggest danger is that you 'just' add the address to the sensitivity list and it all 'works':
always #(cs or wr or addr)
It would probably have helped you if you had first looked up a datasheet of an async RAM. They do not work the way you model it. There data is stored when the CS or Write goes away (which ever first). The data and address have to be stable a certain time before and after that.
In your model you change the address whilst keeping the WR and CS active. In real life the address does not change from one value to another instantaneous. It will go from for example 0000 to 000F but the bits will change one at a time: 0000 => 0004 => 0005 => 000D ==> 000F. Thus you could have messed up the contents of 5 different addresses.
Make a write signal from CS and WR: do_write = cs & wr; Do the actual write when that signal goes away: always #(negedge do_write) .....`.
It appears that you are trying to write an asynchronous RAM. In that case, you need to also add addr and din to your sensitivity list. Also, dout should get mem[addr] when cs is high and wr is low. In your testbench, you need to add a delay in your for loop before supplying the next input. One possible implementation is as follows:
module ram(oe, cs, wr, addr, din, dout);
parameter adds = 6,
wsize = 16,
memsize = 1 << adds;
input cs, wr;
input oe; // output enable
input [adds-1:0] addr;
input [wsize-1:0] din;
output [wsize-1:0] dout;
reg [wsize-1:0] dout;
reg [wsize-1:0] mem [memsize-1:0];
always #(cs, wr, oe, addr, din)
begin
if (cs) begin
if (wr) mem[addr] <= din;
else if (oe) dout <= mem[addr];
end
end
endmodule
And corresponding testbench could be:
module ram_tb;
parameter adds = 6,
wsize = 16,
memsize = 1 << adds;
reg cs, wr;
reg oe; // output enable
reg [adds-1:0] addr;
reg [wsize-1:0] din;
wire [wsize-1:0] dout;
integer k, myseed;
// Instantiate the Unit Under Test (UUT)
ram uut (
.cs(cs),
.wr(wr),
.oe(oe),
.addr(addr),
.din(din),
.dout(dout)
);
initial myseed = 35;
initial begin
for(k = 0; k < memsize; k = k+1) begin
#2
din <= k % 256;
wr <= 1;
cs <= 1;
addr <= k;
oe <= 0;
end
repeat(20) begin
#2
addr <= ($random(myseed)) % memsize ;
wr <= 0;
cs <= 1;
oe <= 1;
$display("Address = %5d, data = %4d", addr, dout);
end
#10 $finish;
end
endmodule

Verilog count odd and even numbers in ram

I'm using quartus 2 9.1 .I have a program of Single-Port RAM on verilog, i added reg
Even
to check is number odd or even by first bit, its 1 or 0 in sumulation. I need to enter 16 numbers in ram by data input, then count how many odd and even numbers. But i tried something like:
output wire [4:0] count;
count = count + data[0]; //to count odd numbers, then i could take away from 16 and get even number - in simulation its just 0 or 1..
or something like that:
output wire [4:0] count;
always #*
begin
if(data[0])
even=1;
else
begin
even=0;
count = count + 1;
end
end
But count dont want show in sumaliton number of odd or even numbers.. My code:
module kok
(
input [7:0] data,
input [5:0] addr,
input we, clk,
output [7:0] q,
output reg even
);
// Declare the RAM variable
reg [7:0] ram[63:0];
// Variable to hold the registered read address
reg [5:0] addr_reg;
always # (posedge clk)
begin
// Write
if (we)
ram[addr] <= data;
addr_reg <= addr;
end
always #(posedge data)
begin
even = data[0];
end
// Continuous assignment implies read returns NEW data.
// This is the natural behavior of the TriMatrix memory
// blocks in Single Port mode.
assign q = ram[addr_reg];
endmodule
My understanding of your question is you want an output count signal that counts how many times you have an even value.
Create a top_level
module top (
input [7:0] data,
input [5:0] addr,
input we
);
reg clk= 1;
initial begin
forever #5 clk = ~clk;
end
reg reset_count = 0;
initial begin
#5 reset_count = 1'b1;
#20 reset_count = 1'b0;
end
kok u_kok (.clk(clk),
.data(data),
.addr(addr),
.we(we),
.reset_count(reset_count)
);
endmodule
Add this to module_kok:
module kok
(
input reset_count,
input [7:0] data,
input [5:0] addr,
input we, clk,
output [7:0] q,
output reg even,
output reg [4:0] count
);
// Declare the RAM variable
reg [7:0] ram[63:0];
// Variable to hold the registered read address
reg [5:0] addr_reg;
always # (posedge clk)
begin
// Write
if (we)
ram[addr] <= data;
addr_reg <= addr;
end
always #(posedge clk)
begin
even <= data[0];
end
always #(posedge even or posedge reset_count)
begin
if (reset_count) begin
count <= 'h0;
end
else begin
count <= count+1'b1;
end
end
// Continuous assignment implies read returns NEW data.
// This is the natural behavior of the TriMatrix memory
// blocks in Single Port mode.
assign q = ram[addr_reg];
endmodule
Note that you can only count to 2**5=32 before the counter overflows.
Here is a working example: https://www.edaplayground.com/x/qRs
The counter needs to be in a clocked process (i.e. inside an always #posedge clk). The counter therefore also needs to be a reg (instead of wire). You also need to figure out which condition(s) should restart your counter, and if you need to accound for overflow conditions etc. This depends on your actual use.

Verilog: Reading 1 bit input and Writing it to 288 bit reg

In verilog, I have a module name(input data,..., output...);
Data is only a single bit input and I need it to be displayed to reg [288:0] data_tmp; to compare the bits. How do I transfer data(input) to the reg?
I tried to handle it like an array in C using a for loop like so:
for(i=0; i<288; i=i+1) begin
data_tmp[i]=data;
end
But it doesn't appear to take any of the values from data or it is overwriting them.
Actual Code:
module inspector (
input rst_n, data, clk,
output total_cnt, skype_cnt, ftp_cnt, https_cnt, telnet_cnt, ssh_cnt, snmp_cnt, smtp_cnt,
nntp_cnt, telnet_session, skype_session, ssh_session
);
output [31:0] total_cnt;
output [7:0] skype_cnt;
output [7:0] ftp_cnt;
output [7:0] https_cnt;
output [7:0] telnet_cnt;
output [7:0] ssh_cnt;
output [7:0] snmp_cnt;
output [7:0] smtp_cnt;
output [7:0] nntp_cnt;
output [7:0] telnet_session;
output [7:0] skype_session;
output [7:0] ssh_session;
localparam INIT = 0;
localparam DATA = 1;
localparam PORT = 2;
localparam TOTAL = 3;
reg [287:0] data_tmp;
reg [3:0] Start_sequence = 32'hA5A5A5A5;
reg [1:0] state;
integer i;
always #(posedge clk)
if (rst_n) begin
total_cnt_tmp = 8'h00;
....
ssh_session_tmp = 8'h00;
end else begin
case (state)
INIT : begin
for(i=0; i<288; i=i+1) begin
data_tmp[i]=data;
end
if (data_tmp[31:0] == Start_sequence) begin
state <= DATA;
end else begin
state <= INIT;
end
end
.....
The for-loop is replicating the data; ie if data is 1 you get 288 ones, if data is 0 you get 288 zeros. What you want what is a shifter. data_tmp shift the bits to the left or right depending on the order of the bit stream.
data_tmp<={data_tmp[286:0],data}; // shift and fill left
or
data_tmp<={data,data_tmp[287:1]}; // shift and fill right
Also, remember to assign flops with non-blocking (<=). Blocking (=) for assigning combinational logic.

Resources