High impedance for output, and undefined output and input for replay buffer - buffer

I'm trying to make a 8 KB replay buffer in Verilog, and when setting up the test-bench and running it, I get undefined states for the output, a high impedance for the ready, and undefined output for the data, as well as an undefined sequence variable. I'm not exactly sure as to how to get the test-bench to display the correct results. I've tried assigning data for the sequence variable, but nothing seems to be working.
My waveform is like this (https://imgur.com/a/hNt1bXU). My reg variables are initialized, and I'm not sure what the issue is in order to get a proper output for the waveform.
Replay Buffer
`timescale 1ns / 1ps
module buffer_top(busy_n,clk,reset_n,ack_nak,seq,tim_out,ready,we,din,dout);
parameter ADDR_WID = 12;
parameter DATA_WID = 16;
parameter DEPTH = 4096; /*MUST be 2^(ADDR_WID)*/
input busy_n,clk,reset_n,tim_out,we;
input[1:0] ack_nak;
input[11:0] seq;
input[DATA_WID-1:0] din;
output ready;
output[DATA_WID-1:0] dout;
wire full,empty,rd,prg,wr,replay;
wire[ADDR_WID-1:0] rd_inc,w_addr,r_addr,replay_addr;
wire[DATA_WID-1:0] dcurrent;
fifoSM u0(clk,reset_n,busy_n,we,ack_nak,seq,tim_out,full,empty,dcurrent,r_addr,ready,rd,prg,wr,rd_inc,replay);
ram u1(clk,r_addr,w_addr,din,dout,wr,rd,dcurrent,replay_addr);
fifo u2(clk,reset_n,wr,rd,prg,replay,rd_inc,full,empty,w_addr,r_addr,replay_addr);
endmodule
FIFO State Machine
`timescale 1ns / 1ps
module fifoSM(clk, reset_n,busy_n,we,ack_nak,seq,tim_out,full,empty,dcurrent,outptr,wrptr,ready,rd,prg,wr,rd_inc,replay );
parameter ADDR_WID = 12;
parameter DATA_WID = 16;
parameter DEPTH = 4096;
input clk,reset_n,busy_n,we,tim_out,full,empty;
input [1:0] ack_nak;
input [DATA_WID-1:0] dcurrent;
input [11:0] seq;
input [12:0] outptr,wrptr;
output reg rd,prg,wr,ready,replay;
output reg[ADDR_WID-1:0] rd_inc;
reg seqFound;
reg [1:0] format,nakcount;
reg [12:0] calc_inc,lastread;
reg [10:0] count;
reg [4:0]state;
localparam idle=5'b00000, s1=5'b00001, s2=5'b00010, s3=5'b00011, s4=5'b00100, s5=5'b00101,s6=5'b00110, s7=5'b00111,
s8=5'b01000,s9=5'b01001,s10=5'b01010,s11=5'b01011,s12=5'b01100,s13=5'b01101,s14=5'b01110;
always#(posedge clk)
begin
if(!reset_n)begin
state <= idle;
nakcount <= 2'd0;
end
else begin
case(state)
idle: begin
if(busy_n && !empty && outptr !=wrptr) //read buffer if not empty and lane is open
state <= s3;
else if(ack_nak == 10 && !empty)begin //handle nak if not empty
if(nakcount == 2'b11) //if replay count full go to retrain state
state <= s14;//retrain state
else begin //else go to purge section then after to replay states
state <= s8; //purge state
nakcount <= nakcount + 1;
end
end
else if(ack_nak == 2'b01 && !empty)begin//handle ack if not empty
state <= s8; //go to purge section
nakcount <= 2'd0; //reset replay counter
end
else if(tim_out && !empty)begin //handle time out if not empty
if(nakcount == 2'b11)//if replay count full
state <= s14;//go to retrain section
else begin //else go to replay state
state <= 11;
nakcount <= nakcount + 1; //increment replay count
end
end
else if(we && !full) //write packet if not full and is we
state <= s1;
end
//write states (input)
s1: begin
state <= s2;
end
s2: begin
if(we)
state <= s2;
else
state <= idle;
end
//read states (output) output rd=1 to fifo
s3: begin
state <= s4;
count <= 0;
end
s4: begin
state <=s5;
count <= 1;
format = dcurrent[14:13];
if(format[0]==0)begin
calc_inc = 13'd8; //3dw including 1dw for lcrc
end
else
calc_inc = 13'd10;
end
s5: begin
count <= 2;
if(dcurrent[9:0] == 0)
calc_inc = calc_inc + (format[1] * 2048);
else
calc_inc = calc_inc + (format[1] * dcurrent[9:0]*2);
state <= s6;
end
s6: begin
count <= count + 1;
if(count < calc_inc)
state <= s6;
else
state <= idle;
end
//purge
s8: begin //let rd_ptr increment r_ptr until found or do this
if(dcurrent == {"0000",seq})begin
state <=s9;
seqFound <= 1;
end
else begin
seqFound <=0;
end
end
s9: begin //get format fields to get header length, output to fifo: prg = 1
state <=s10;
format = dcurrent[14:13];
if(format[0]==0)begin
calc_inc = 13'd8; //3dw including 1dw for lcrc
end
else
calc_inc = 13'd10;
end
s10: begin //get length fields to add to increment
if(dcurrent[9:0] == 0)
calc_inc = calc_inc + (format[1] * 2048);
else
calc_inc = calc_inc + (format[1] * dcurrent[9:0]*2);
if(seqFound)begin //if done purging
if(ack_nak==2'b01) //if ack go to idle
state <=idle;
else begin //if nak go to replay states
state <= s11;
end
end
else
state <= s8; //examine next seq num in buffer to compare with dllp seq num
end
//replay states
s11: begin //set up lastread before enter replay mode
state <= s12;
lastread <= outptr; //set lastread to outptr before outptr changes in replay
end
s12: begin //output replay = 1 to fifo
state <= s13; //outptr will go back to where r_addr is
end
s13: begin //output read = 1 to fifo and repeat until outptr retruns to where it was
if(outptr < lastread)
state <=s13; //repeat this state
else
state <= idle; //if outptr back to where was go back
end
s14: state<= s14; //link retrain
default: begin state <= idle; end
endcase
end
end
always#(state)
case(state)
idle: begin replay = 0; ready = 0; rd = 0; wr = 0; prg = 0;end
s1: begin ready = 1; wr = 1; end
s2: begin wr = 1; end
s4: begin rd = 1; end
s8: begin ready = 0; rd = 0; wr =0; prg = 1; rd_inc = 1; end
s9: begin rd_inc = 1; end
s10: begin rd_inc = calc_inc; end
s11: begin replay = 0; ready = 0; rd = 0; wr =0; prg = 0;end //setup lastread with outptr
s12: begin replay = 1; end
s13: begin replay = 0; rd = 1; end
s14: begin ready = 0; rd = 0; wr= 0; prg= 0; end
default: begin ready = 1; rd = 0; wr = 0; prg = 0; end
endcase
endmodule
RAM
`timescale 1ns / 1ps
module ram(clk, r_addr, w_addr, din, dout, wr, rd, dcurrent, replay_addr);
parameter ADDR_WID = 12;
parameter DATA_WID = 16;
parameter DEPTH = 4096;
input clk, wr, rd;
input [ADDR_WID-1:0] r_addr, w_addr, replay_addr;
input [DATA_WID-1:0] din;
output [DATA_WID-1:0] dout, dcurrent;
reg [DATA_WID-1:0] dataout;
reg [DATA_WID-1:0] mem [0:DEPTH-1];
assign dout = (rd && !wr) ? dataout: 16'hzzzz;
assign dcurrent = mem[replay_addr];
always#(posedge clk) begin
if(wr) mem[w_addr] = din;
end
always#(posedge clk) begin
dataout = mem[r_addr];
end
endmodule
FIFO
module fifo(clk,reset_n,wr,rd,prg,replay,rd_inc,full,empty,w_addr,r_addr,replay_addr);
parameter ADDR_WID = 12;
parameter DATA_WID = 16;
parameter DEPTH = 4096;
input clk, reset_n, wr, rd, prg, replay;
input [ADDR_WID-1:0] rd_inc;
output full, empty;
output [ADDR_WID-1:0] w_addr, r_addr, replay_addr;
reg [ADDR_WID-1:0] w_ptr, replay_ptr, r_ptr;
always#(posedge clk)
begin
if(!reset_n)
begin
w_ptr <= 0;
replay_ptr <= 0;
r_ptr <= 0;
end
else
if(wr && !full)
w_ptr <= w_ptr + 1;
if(prg && !empty)begin
replay_ptr <= replay_ptr + rd_inc; //or long way and check every address for seq num
end
if(rd && !empty)
r_ptr <= r_ptr + 1;
if(replay)
r_ptr <= replay_ptr;
end
assign full = ((r_ptr!=w_ptr) && (r_ptr[ADDR_WID-1:0]==w_ptr[ADDR_WID-1:0]))?1:0;
assign empty = (r_ptr==w_ptr) ? 1 : 0;
assign w_addr = w_ptr[ADDR_WID-1:0];
assign out_addr = r_ptr[ADDR_WID-1:0];
assign replay_addr = replay_ptr[ADDR_WID-1:0];
endmodule
Replay Buffer Testbench
`timescale 1ns / 1ps
module buffer_top_tb();
parameter ADDR_WID = 12;
parameter DATA_WID = 16;
parameter DEPTH = 4096; /*MUST be 2^(ADDR_WID)*/
reg busy_n,clk,reset_n,tim_out,we;
reg[1:0] ack_nak;
reg[11:0] seq;
reg[DATA_WID-1:0] din;
wire ready;
wire[DATA_WID-1:0] dout;
buffer_top u3(busy_n,clk,reset_n,ack_nak,seq,tim_out,ready,we,din,dout);
always #2 clk = ~clk;
initial begin
clk = 0; reset_n = 0; busy_n = 0; ack_nak = 2'b00; tim_out = 0; we = 0; //initial state, everything zeroed out
#3;
reset_n = 1;
/*Writing packets to buffer*/
we = 1;
//Memory Read Request to read DW at address 3F6BFC11C and return result to entity with ID 0x0000
din = 16'h01a4; seq = 0; //seq# 420
#4; din = 16'h0000; #4; din = 16'h0001; //DW0
#4; din = 16'h0000; #4; din = 16'h0c0f; //DW1
#4; din = 16'hfdaf; #4; din = 16'hf047; //DW2
#4; din = 16'h0f0f; #4; din = 16'hf0f0; //LCRC
#4;
//Completion TLP w data 0xba5eba11
din = 16'h01a5; seq = 1; //seq# 421
#4; din = 16'h4A00; #4; din = 16'h0001;
#4; din = 16'h0100; #4; din = 16'h0004;
#4; din = 16'h0000; #4; din = 16'h0C40;
#4; din = 16'hba5e; #4; din = 16'hba11;
#4; din = 16'h0F0F; #4; din = 16'hf0f0;
#4;
//Memory Write Request 4DW + 1DW data
din = 16'h01a6; seq = 2; //seq# 422
#4; din = 16'h6000; #4; din = 16'h0001;
#4; din = 16'h0000; #4; din = 16'h000F;
#4; din = 16'hFDAF; #4; din = 16'hF040;
#4; din = 16'hFCBA; #4; din = 16'h57ED;
#4; din = 16'h9ABC; #4; din = 16'hDEF1;
#4; din = 16'h0F0F; #4; din = 16'hf0f0;
#4;
//Memory Write Request 3DW + 1DW data
din = 16'h01a7; seq = 3; //seq# 423
#4; din = 16'h4000; #4; din = 16'h0001;
#4; din = 16'h0000; #4; din = 16'h000F;
#4; din = 16'hFDAF; #4; din = 16'hF040;
#4; din = 16'h9ABC; #4; din = 16'hDEF1;
#4; din = 16'h0F0F; #4; din = 16'hf0f0;
#4;
//IO Rd request 3DW no Data
din = 16'h01a8; seq = 4; //seq# 424
#4; din = 16'h0200; #4; din = 16'h0001;
#4; din = 16'h0000; #4; din = 16'h000F;
#4; din = 16'hFDAF; #4; din = 16'hF040;
#4; din = 16'h0F0F; #4; din = 16'hf0f0;
#4;
/*End write phase*/
#20;
$stop;
end
endmodule

When I compile your code, I get several warnings. This is the 1st:
fifoSM u0(clk,reset_n,busy_n,we,ack_nak,seq,tim_out,full,empty,dcurrent,r_addr,ready,rd,prg,wr,rd_inc,replay);
|
xmelab: *W,CUVWSP 1 output port was not connected:
xmelab: replay
This points to a connection error in your design.
When you compare the fifoSM module instance line to the module declaration line, you will see that the ready signal is not connected properly. It is connected to wrptr instead of ready. This causes the high impedance (z) on ready at the top level.
If you fix these connection problems, perhaps your other errors will be fixed as well.
If you didn't get compile warnings with your simulator, try your code on multiple simulators on edaplayground.
In order to avoid common connection problems like this, it is better to use connection-by-name instead of connection-by-position. Refer to IEEE Std 1800-2017, section 23.3.2.2 Connecting module instance ports by name. For example, to instantiate the fifoSM module, use something like this:
fifoSM dut (
// Inputs:
.ack_nak (ack_nak),
.busy_n (busy_n),
.clk (clk),
.dcurrent (dcurrent),
.empty (empty),
.full (full),
.outptr (outptr),
.reset_n (reset_n),
.seq (seq),
.tim_out (tim_out),
.we (we),
.wrptr (wrptr),
// Outputs:
.prg (prg),
.rd (rd),
.rd_inc (rd_inc),
.ready (ready),
.replay (replay),
.wr (wr)
);

Related

Why the memory content is not read? - verilog digital system design

I created a microsystem which is composed of two clocked SRAMs, one designed for storing instruction-codes, and another to store some output values. The instruction SRAM has an interface module, named "user" which provides a mechanism to ease the writing process, consequently, when writing data in the memory, there is no need to specify the corresponding memory address at which those instructions have to be stored. Similarly, when reading data from the second SRAM, there is no need to specify the corresponding memory address from which data is extracted, thanks to "display" module. To be more specific, when writing data in the instructions memory, a counter increments the address pointer after each writing, while the second memory has another counter which increments the address pointer value after each reading. When one tries to read information from the instruction memory, they have to specify the memory address from which data should be read, and, as expected, when one tries to write information in the output memory, they have to specify the memory address in which data should be written. Furthermore, the microsystem has an automaton which takes input data from the instruction memory and processes it. After processing information, the automaton stores some output values in the output memory. I come across an issue when simulating, because, apparently, the read values from the SRAM memory cannot be seen, namely, rd_data_instrucions, thus, neither the input values "in" for the automaton cannot be found, nor the output values, as long as they depend on the data read from the first SRAM. I posted the code below and a diagram.
//wishbone module
module wishbone(
input clk,rst,
output reg [2:0]in,
output reg wr_en_instructions,wr_en_display,
input [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
output reg [3:0] wr_data_display,
output [2:0] rd_data_instructions,
output [3:0] rd_data_display,//created for user, in order to make possible the display
output [12:0]o
);
reg [15:0] pointer_instructions,pointer_display;
initial wr_en_instructions = 1'b1;//?
control_unit i0(.clk(clk),.rst(rst),.in(in),.o(o));
user i1(.clk(clk),.wr_en(wr_en_instructions),.address_in(pointer_instructions),.wr_data(wr_data_instructions),.rd_data(rd_data_instructions));
display i2(.clk(clk),.wr_en(wr_en_display),.address_in(pointer_display),.wr_data(wr_data_display),.rd_data(rd_data_display));
integer i = 0;
always # * begin
wr_en_display = ~wr_en_instructions;
end
always #(posedge clk) begin
if(rst) begin
wr_en_instructions <= 1'b1;
pointer_instructions <= 16'd0;
pointer_display <= 16'd0;
end
else begin
if(wr_en_instructions) begin
if(wr_data_instructions[2] == 1'b1) begin
pointer_instructions <= 16'd0;
pointer_display <= 16'd0;
wr_en_instructions <= 1'b0;
end
end
else begin
in <= rd_data_instructions;
pointer_instructions <= pointer_instructions + 1;
if(rd_data_instructions == 3'b010) begin
wr_data_display <= o;
pointer_display <= pointer_display + 1;
end
else if(rd_data_instructions == 3'b100) begin
wr_en_instructions <= 1'b1;
end
end
end
end
endmodule
//testbench for top module
module wishbone_tb(
output reg clk,rst,
output [2:0]in,
output wr_en_instructions,wr_en_display,
output reg [2:0] wr_data_instructions,//created for usr, in order to make possible to write data
output [3:0] wr_data_display,
output [2:0] rd_data_instructions,
output [3:0] rd_data_display,//created for user, in order to make possible the display
output [12:0]o
);
wishbone cut(
.clk(clk),.rst(rst),
.in(in),
.wr_en_instructions(wr_en_instructions),.wr_en_display(wr_en_display),
.wr_data_instructions(wr_data_instructions),
.wr_data_display(wr_data_display),
.rd_data_instructions(rd_data_instructions),
.rd_data_display(rd_data_display),
.o(o)
);
initial $dumpvars(0,wishbone_tb);
initial begin
clk = 1'b1;
repeat (600000)
#100 clk = ~clk;
end
initial begin
rst = 1'b1;
#400 rst = 1'b0;
end
initial begin
wr_data_instructions = 3'd1;
#3000400 wr_data_instructions = 3'd2;
#1000000 wr_data_instructions = 3'd1;
#3000000 wr_data_instructions = 3'd0;
#2000000 wr_data_instructions = 3'd3;
#1000000 wr_data_instructions = 3'd1;
#3000000 wr_data_instructions = 3'd4;//halt
end
endmodule
//code for the first memory:
//stores instructions
module sram_1port_instructions(
input clk,//clocked memory
input wr_en,//when high, data is writeen, otherwise is read
input [15:0] address_in,//suppose timer cannot count more than 13ms
input [2:0] wr_data,//3 bit instructions
output reg [2:0] rd_data
);
reg [2:0] memory [2 ** 15 - 1 : 0];
always #(posedge clk) begin
if(wr_en) memory[address_in] <= wr_data;
else rd_data <= memory[address_in];
end
endmodule
//user interface designed for the first memory
module user(
input clk,
input wr_en,
input [15:0] address_in,
input [2:0] wr_data,
output [2:0] rd_data
);
reg [15:0] pointer,address;
initial pointer = 16'd0;
sram_1port_instructions i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));
always #(posedge clk) begin
if(wr_en) begin
address <= pointer;
pointer <= pointer + 1;
end
else begin
address <= address_in;
pointer <= 16'd0;
end
end
endmodule
//user tb
module user_tb(
output reg clk, wr_en,
output reg [15:0] address_in,
output reg [2:0] wr_data,
output [2:0] rd_data
);
user cut(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));
initial $dumpvars(0,user_tb);
initial begin
clk = 1'd1;
repeat (2000)
#100 clk = ~clk;
end
initial begin
wr_en = 1'd1;
#100000 wr_en = 1'd0;
end
integer i;
initial begin
wr_data = 3'd0;
for(i = 1;i < 500;i = i + 1) begin
#200 wr_data = i;
end
end
initial begin
address_in = 16'd0;
#100000 address_in = 16'd0;
for(i = 1;i < 500;i = i + 1) begin
#200 address_in = i;
end
end
endmodule
//code for the second memory:
//stores output data
module sram_1port_data(
input clk,//clocked memory
input wr_en,//when high, data is written, otherwise is read
input [15:0] address_in,//suppose timer cannout count more than 13ms
input [3:0] wr_data,//memory does not sotre values greater than 13(ms)
output reg [3:0] rd_data
);
reg [3:0] memory [2 ** 15 - 1 : 0];
always #(posedge clk) begin
if(wr_en) memory[address_in] <= wr_data;
else rd_data <= memory[address_in];
end
endmodule
//display interfacedesigned for the second memory
module display(
input clk,
input wr_en,
input [15:0] address_in,
input [3:0] wr_data,
output [3:0] rd_data
);
reg [15:0] pointer,address;
initial pointer = 16'd0;
sram_1port_data i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));
always #(posedge clk) begin
if(!wr_en) begin
address <= pointer;
pointer <= pointer + 1;
end
else begin
address <= address_in;
pointer <= 16'd0;
end
end
endmodule
//tb for display
module display_tb(
output reg clk,
output reg wr_en,
output reg [15:0] address_in,
output reg [3:0] wr_data,
output [3:0] rd_data
);
display i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));
initial $dumpvars(0,display_tb);
initial begin
clk = 1'd1;
repeat (2000)
#100 clk = ~clk;
end
initial begin
wr_en = 1'd1;
#100000 wr_en = 1'd0;
end
integer i;
initial begin
wr_data = 3'd0;
address_in = 16'd0;
for(i = 1;i < 500;i = i + 1) begin
#200;
wr_data = i;
address_in = i;
end
end
endmodule
//code for the control unit:
//control unit
module control_unit(
input clk,rst,
input [2:0]in,
output [12:0]o
);
wire f,g;
automaton i0(.clk(clk),.rst(rst),.in(in),.clr(f),.en(g));
circuit i1(.clk(clk),.clr(f),.en(g),.o(o));
endmodule
//code for automaton:
//atuomaton
module automaton(
input clk,rst,
input [2:0]in,
output reg clr,en
);
localparam S0_ST = 2'b00;
localparam S1_ST = 2'b01;
localparam S2_ST = 2'b10;
reg [1:0] st_reg,st_nxt;
always # * begin
case(st_reg)
S0_ST: if(!in[1]) st_nxt = S0_ST;
else if(in[0]) st_nxt = S2_ST;
else st_nxt = S1_ST;
S1_ST: if(!in[0]) st_nxt = S1_ST;
else if(in[1]) st_nxt = S2_ST;
else st_nxt = S0_ST;
S2_ST: if(in == 2'd1) st_nxt = S0_ST;
else st_nxt = S2_ST;
endcase
end
always # * begin
case(st_reg)
S0_ST: {clr,en} = 2'd1;
S1_ST: {clr,en} = 2'd0;
S2_ST: clr = 1'd1;
endcase
end
always #(posedge clk) begin
if(rst) st_reg <= S2_ST;
else st_reg <= st_nxt;
end
endmodule
//code for circuit:
//circuit
module circuit(
input clk,clr,en,
output [12:0] o
);
wire f;
generator i0(.clk(clk),.clr(clr),.en(en),.o(f));
counter i1(.clk(clk),.clr(clr),.en(f),.o(o));
endmodule
//code for counter:
//counter
module counter(
input clk,clr,en,
output reg [12:0] o
);
reg [12:0] st_nxt;
always # (posedge clk) begin
if(clr) o <= 13'd0;
else o <= st_nxt;
end
always # *
if(en) st_nxt = o + 1;
else st_nxt = o;
endmodule
//code for generator:
//pulse generator
module generator(
input clk,clr,en,
output reg o
);
reg [12:0] st_reg,st_nxt;
always #(posedge clk) begin
if(clr) st_reg <= 13'd0;
else st_reg <= st_nxt;
end
always # * begin
if(en) begin
if(st_reg == 13'd4999) begin
st_nxt = 13'd0;
o = 1'b1;
end
else begin
st_nxt = st_reg + 1;
o = 1'b0;
end
end
else begin
if(st_reg == 13'd4999) begin
st_nxt = 13'd0;
o = 1'b0;
end
else begin
st_nxt = st_reg;
o = 1'b0;
end
end
end
endmodule
When you read from address 0x8001, that is beyond the limit of your memory size. You could increase your memory. Change:
reg [2:0] memory [2 ** 15 - 1 : 0];
to:
reg [2:0] memory [2 ** 16 - 1 : 0];
This gets rid of the unknown (X) when you read from address 0x8001.
Or, if you don't want to enlarge the memory, make sure you limit your addresses.

I see undefined output sequences reading a memory in simulation

I have a question related to the implementation of a clocked SRAM memory which is is supposed to store data written by user and then display the memory content. In addition, I created a module named display which eases the reading process so that there is no need to provide the memory address from which data should be extracted, by incrementing a register after each reading. Nevertheless, when I simulate the circuit, I cannot see the correct output; thus, when I read the memory, I notice some undefined output sequences. I posted the corresponding code below.
//stores output data
module sram_1port_data(
input clk,//clocked memory
input wr_en,//when high, data is written, otherwise is read
input [15:0] address_in,//suppose timer cannout count more than 13ms
input [3:0] wr_data,//memory does not sotre values greater than 13(ms)
output reg [3:0] rd_data
);
reg [3:0] memory [2 ** 15 - 1 : 0];
always #(posedge clk) begin
if(wr_en) memory[address_in] <= wr_data;
else rd_data <= memory[address_in];
end
endmodule
//display interfacedesigned for the second memory
module display(
input clk,
input wr_en,
input [15:0] address_in,
input [3:0] wr_data,
output [3:0] rd_data
);
reg [15:0] pointer,address;
initial pointer = 16'd0;
sram_1port_data i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));
always #(posedge clk) begin
if(!wr_en) begin
address <= pointer;
pointer <= pointer + 1;
end
else address <= address_in;
end
endmodule
//tb for display
module display_tb(
output reg clk,
output reg wr_en,
output reg [15:0] address_in,
output reg [3:0] wr_data,
output [3:0] rd_data
);
display i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));
initial $dumpvars(0,display_tb);
initial begin
clk = 1'd1;
repeat (2000)
#100 clk = ~clk;
end
initial begin
wr_en = 1'd1;
#100000 wr_en = 1'd0;
end
integer i;
initial begin
wr_data = 3'd0;
for(i = 1;i < 500;i = i + 1) begin
#200 wr_data = i;
end
end
initial begin
address_in = 16'd0;
for(i = 1;i < 500;i = i + 1) begin
#200 address_in = i;
end
end
endmodule
When I look at waveforms, I see that rd_data is unknown (X) on every other read. Looking at an internal address signal, I see that the unknowns are only for even addresses. Early in the simulation, you are only writing to even addresses.
In your testbench, you are using the same variable (i) in 2 different for loops. In your 2nd for loop, use a different variable name (j, for example):
integer j;
initial begin
address_in = 16'd0;
for(j = 1;j < 500;j = j + 1) begin
#200 address_in = j;
end
end
Now, all reads have known values because it writes to all addresses (even and odd).
You could also set the address inside the same for loop as the write data. This is likely a better approach in this case.
initial begin
wr_data = 3'd0;
address_in = 16'd0;
for(i = 1;i < 500;i = i + 1) begin
#200;
wr_data = i;
address_in = i;
end
end

How can I fix this syntax error: unexpected INTEGER NUMBER?

I try to build a 4-bit CPU which can implement ADD(000), AND(001), OR(010), NOT(011), SLT(100), SM(101), LM(110), and LI(111), and I get the following errors:
Error: (vlog-13069) D:/modelsim/examples/cpu.v(48): near "=": syntax
error, unexpected '=', expecting ++ or --.
Error: (vlog-13069) D:/modelsim/examples/cpu.v(53): near "3": syntax
error, unexpected INTEGER NUMBER.
Error: (vlog-13069) D:/modelsim/examples/cpu.v(56): near "and": syntax
error, unexpected and.
How can I fix it?
The following is my Verilog code:
module cpu(instruction, register0, register1, register2, register3,
memory0, memory1, memory2, memory3, memory4, memory5, memory6, memory7,
memory8, memory9, memory10, memory11, memory12, memory13, memory14, memory15, overflow);
input [8:0] instruction;
output [3:0] register0; output [3:0] register1; output [3:0] register2; output [3:0] register3;
output [3:0] memory0; output [3:0] memory1; output [3:0] memory2; output [3:0] memory3;
output [3:0] memory4; output [3:0] memory5; output [3:0] memory6; output [3:0] memory7;
output [3:0] memory8; output [3:0] memory9; output [3:0] memory10; output [3:0] memory11;
output [3:0] memory12; output [3:0] memory13; output [3:0] memory14; output [3:0] memory15;
output overflow;
//there are 8 kinds of op code for u to choose.
//u can save four nums in register, or save 16 nums in memory. there's also a num for u to check it's overflow or not
reg overflow;
reg [3:0] register [3:0];
reg [3:0] memory [15:0];
reg [1:0] rs, rt, rd;
reg [2:0] op;
//create four 4-bits registers, and sixteen 4-bits memories.
//rs, rt, rd are the addresses of the register or memory
reg [3:0] c, a, b, address;
reg [4:0] sum;
//a, b used to calculate the num stored in register or memory
//address is the address of memory
//for checking out the overflowing, we need 'sum' to be 5-bits
integer i;
initial
begin
for (i = 0; i < 4; i = i + 1)
register [i] = 4'b0000;
for (i = 0; i < 16; i = i + 1)
memory[i] = 4'b0000;
end
//initialize all the register and memory
//your code~
always#(*)begin
op = instruction[8:6];
rs = instruction[5:4];
rt = instruction[3:2];
rd = instruction[1:0];
case(op)
3'b000:
a = register[rs];
b = register[rt];
sum = a + b;
overflow = sum[4];//if overflow is 1, then it does.
register[rd] = sum;
3'b001:
a = register[rs];
b = register[rt];
and f0(c[0], a[0], b[0]);
and f1(c[1], a[1], b[1]);
and f2(c[2], a[2], b[2]);
and f3(c[3], a[3], b[3]);
register[rd] = c;
3'b010:
a = register[rs];
b = register[rt];
or f0(c[0], a[0], b[0]);
or f1(c[1], a[1], b[1]);
or f2(c[2], a[2], b[2]);
or f3(c[3], a[3], b[3]);
register[rd] = c;
3'b011:
a = register[rs];
b = register[rt];
not f0(c[0], a[0], b[0]);
not f1(c[1], a[1], b[1]);
not f2(c[2], a[2], b[2]);
not f3(c[3], a[3], b[3]);
register[rd] = c;
3'b100:
a = register[rs];
b = register[rt];
if(a < b) begin
register[rd] = 4'b0001;end
else begin
register[rd] = 4'b0000;end
3'b101:
address = instruction[3:0];
memory[address] = register[rs];//can i really write like this?
3'b110:
address = instruction[5:2];
register[rd] = memory[address];//can i really write like this?
3'b111:
a = instruction[5:2];
register[rd] = a;
endcase
end
assign register0 = register[0]; assign register1 = register[1];
assign register2 = register[2]; assign register3 = register[3];
assign memory0 = memory[0]; assign memory1 = memory[1];
assign memory2 = memory[2]; assign memory3 = memory[3];
assign memory4 = memory[4]; assign memory5 = memory[5];
assign memory6 = memory[6]; assign memory7 = memory[7];
assign memory8 = memory[8]; assign memory9 = memory[9];
assign memory10 = memory[10]; assign memory11 = memory[11];
assign memory12 = memory[12]; assign memory13 = memory[13];
assign memory14 = memory[14]; assign memory15 = memory[15];
endmodule
Multiple lines in a case statement branch must be enclosed between begin and end, eg
3'b000:
begin
a = register[rs];
b = register[rt];
sum = a + b;
overflow = sum[4];//if overflow is 1, then it does.
register[rd] = sum;
end

Incorrect Indexing in Rader Algorithm (GNU Octave implementation)

Rader DFT algorithm implemented using GNU Octave (for example, length 11). I used this wikipedia article. The values obtained are correct, but they are incorrectly reindexed. I can not understand where the error is?
upd. Add function for finds the smallest generator of the group.
Fin = [1,2,3,4,5,6,7,8,9,10,11];
nfft = columns(Fin);
snfft = nfft - 1;
function [m one_per] = find_gen(p)
m = 1;
a = factor(p);
if (length(a) > 1)
m = p + 1;
one_per = [];
endif
if (m == 1)
finished = 0;
for cur = 2:p-2
not_yet = 0;
test = cur;
single_per = [1 cur];
for k = 2:p-2
test = test * cur;
test = mod(test,p);
single_per = [single_per test];
if (test == 1)
not_yet = 1;
endif
endfor
if (not_yet == 0)
m = cur;
one_per = single_per;
finished = 1;
break;
endif
endfor
endif
endfunction
q = find_gen(nfft)
p = mod((q^(nfft-2)),nfft)
Tq_idx = [];
Tq = [];
for k = 0 : snfft-1
A = mod(q^k, nfft);
Tq_idx = [A Tq_idx];
Tq = [Fin(A+1) Tq];
endfor
Tq_idx, Tq
Tp_idx = [];
Tp = [];
for k = 0 : snfft-1
A = mod(p^k, nfft);
Tp_idx = [A Tp_idx];
Tp = [Fin(A+1) Tp];
endfor
Tp_idx, Tp
Twp = [];
for k = 1 : snfft
ecpx = complex(cos(-2*pi*Tp_idx(k) / nfft),sin(-2*pi*Tp_idx(k) / nfft));
Twp = [Twp ecpx];
endfor
Tq_fft = fft(Tq);
Twp_fft = fft(Twp);
Tm_fft = Tq_fft .* Twp_fft;
Tm_ffti = ifft(Tm_fft);
Tm_ffti
Res = [Fin(1)];
for k = 1 : snfft
Res(1) += Fin(k+1);
Res = [Res (Tm_ffti(Tp_idx(k)) + Fin(1))];
endfor
Res
Fbest = fft(Fin)
Fdiff = Fbest .- Res
ResI = ifft(Res)
Result
Res =
Columns 1 through 3:
66.0000 + 0.0000i -5.5000 - 4.7658i -5.5000 - 18.7313i
Columns 4 through 6:
-5.5000 - 0.7908i -5.5000 - 8.5582i -5.5000 + 8.5582i
Columns 7 through 9:
-5.5000 + 18.7313i -5.5000 + 4.7658i -5.5000 + 0.7908i
Columns 10 and 11:
-5.5000 - 2.5118i -5.5000 + 2.5118i
Using the GNU Octave fft () internal function as standard
Fbest =
Columns 1 through 3:
66.0000 + 0.0000i -5.5000 + 18.7313i -5.5000 + 8.5582i
Columns 4 through 6:
-5.5000 + 4.7658i -5.5000 + 2.5118i -5.5000 + 0.7908i
Columns 7 through 9:
-5.5000 - 0.7908i -5.5000 - 2.5118i -5.5000 - 4.7658i
Columns 10 and 11:
-5.5000 - 8.5582i -5.5000 - 18.7313i
I fixed the error. Working code here
function [m one_per] = find_gen(p)
m = 1;
a = factor(p);
if (length(a) > 1)
m = p + 1;
one_per = [];
endif
if (m == 1)
finished = 0;
for cur = 2:p-2
not_yet = 0;
test = cur;
single_per = [1 cur];
for k = 2:p-2
test = test * cur;
test = mod(test,p);
single_per = [single_per test];
if (test == 1)
not_yet = 1;
endif
endfor
if (not_yet == 0)
m = cur;
one_per = single_per;
finished = 1;
break;
endif
endfor
endif
endfunction
function [Fout] = fast_conv (F1,F2, seq_lenght)
F1_fft = fft(F1);
F2_fft = fft(F2);
Fm_fft = F1_fft .* F2_fft;
Fout = ifft(Fm_fft);
endfunction
function [Res] = rader_algo (Fin)
nfft = columns(Fin);
snfft = nfft - 1;
q = find_gen(nfft)
p = mod((q^(nfft-2)),nfft)
Tq_idx = []; Tq = [];
for k = 0 : snfft-1
A = mod(q^k, nfft);
Tq_idx = [Tq_idx A];
Tq = [Tq Fin(A+1)];
endfor
Tq_idx, Tq
Tp_idx = []; Tp = [];
for k = 0 : snfft-1
A = mod(p^k, nfft);
Tp_idx = [Tp_idx A];
Tp = [Tp Fin(A+1)];
endfor
Tp_idx, Tp
Twp = [];
for k = 1 : snfft
ecpx = complex(cos(-2*pi*Tp_idx(k) / nfft),sin(-2*pi*Tp_idx(k) / nfft));
Twp = [Twp ecpx];
endfor
Twp
Tm_ffti = fast_conv(Tq, Twp, nfft);
Res = zeros(1, nfft);
Res(1) = Fin(1);
for k = 1 : snfft
Res(1) += Fin(k+1);
Res(Tp_idx(k)+1) = Tm_ffti(k) + Fin(1);
endfor
endfunction
Fin = [1,2,3,4,5];
Res = rader_algo (Fin)
% === VERIFY ===
Fbest = fft(Fin)
Fdiff = Fbest .- Res
ResI = ifft(Res)

My stack (LIFO) memory overflows and prevents any further reading of memory

I've been working on coding a simple stack memory. It has 4 address bits and thus can store 16 elements. Everything works fine, but the problem is that when all 16 memory elements have been written to, the counter that keeps track of the memory location overflows and resets it to 0000. I cannot find out the reason for this. All my registers are of correct width.
reg_push and reg_pop are incremented and decremented together, and these are the registers that keep track of the memory location.
Here is the simulation showing the overflow.
Here is the code:
module stack # (parameter dbits = 3, abits = 4)(
input clock,
input reset,
input push,
input pop,
input [dbits-1:0] din,
output [dbits-1:0] dout,
output full,
output empty
);
reg [dbits-1:0] regarray[2**abits-1:0]; //number of words in fifo = 2^(number of address bits)
reg [abits-1:0] reg_push, reg_pop, next_push, next_pop;
reg full_reg, empty_reg, full_next, empty_next;
reg [dbits-1:0] out;
wire wr_en;
wire db_push, db_pop;
reg dffpop1, dffpop2, dffpush1, dffpush2;
always # (posedge clock) dffpush1 <= push;
always # (posedge clock) dffpush2 <= dffpush1;
assign db_push = ~dffpush2 & dffpush1; //monostable multivibrator to detect only one pulse of the button
always # (posedge clock) dffpop1 <= pop;
always # (posedge clock) dffpop2 <= dffpop1;
assign db_pop = ~dffpop2 & dffpop1; //monostable multivibrator to detect only one pulse of the button
assign wr_en = db_push & ~full; //only push if write signal is high and stack is not full
//always block for write operation
always # (posedge clock)
if(wr_en) regarray[reg_push] = din;
//always block for read operation
always # (posedge clock)
begin
if(db_pop)
out <= regarray[reg_pop];
end
always # (posedge clock or posedge reset)
begin
if(reset)
begin
full_reg <= 0;
empty_reg <= 1;
reg_push <= 0;
reg_pop <= 0;
end
else
begin
full_reg <= full_next;//created the next registers to avoid the error of mixing blocking and non blocking assignment to the same signal
empty_reg <= empty_next;
reg_push <= next_push;
reg_pop <= next_pop;
end
end
always # (*)
begin
full_next = full_reg; //default values stay the same
empty_next = empty_reg;
next_push = reg_push;
next_pop = reg_pop;
if(db_push)
begin
if(~full) //if stack is not full continue
begin
empty_next = 0;
next_push = reg_push + 1;
next_pop = reg_pop + 1;
if(reg_push == (2**abits - 1)) full_next = 1; //all registers have been written to
end
end
else if (db_pop)
begin
if(~empty) //if stack is not empty continue
begin
full_next = 0;
next_pop = reg_pop - 1;
next_push = reg_push - 1;
if(reg_pop == 0) empty_next = 1; //all data has been read
end
end
end
assign full = full_reg;
assign empty = empty_reg;
assign dout = out;
endmodule
Now if I use this stack without making it reach its full capacity, it will work perfectly. It's only when I store all 16 elements into it that the problem arises.
Extend your pop pointer an extra bit.
A 4-bit register can only store the a value 0 through 15. Any value above that will ignore the upper bits, effectively doing a mod 16. Hence assigning 16 will result in 0.
Option 1: expand to a 5-bit register:
Try changing:
reg [abits-1:0] reg_push, reg_pop, next_push, next_pop;
To:
reg [abits:0] reg_push, reg_pop, next_push, next_pop;
Option 2: Use full_reg are the 5th bit in evaluations:
Change:
if(reg_push == (2**abits - 1)) full_next = 1; //all registers have been written to
...
if(reg_pop == 0) empty_next = 1; //all data has been read
To:
if({full_reg,reg_push} >= (2**abits - 1)) full_next = 1; //all registers have been written to
...
if({full_reg,reg_pop} == 0) empty_next = 1; //all data has been read

Resources