Test Bench code won't work in verilog for pipelined processor - verilog

I am designing a simple pipeline processor in verilog. I think my code is fine, but nothing happens when I run my test bench. I instantiate all my variables but my always blocks seem to be being ignored. I have copies of my processor code and test bench below.
Processor:
module Processor(output [0:15]pc, output [0:31]Instruction, output [0:31] readData1, output [0:31]readData2, output clk
);
// IF Stuff
reg clk, PCSrc;
reg [0:15]pc;
reg [0:15]add;
reg [0:15]jump;
wire [0:31]Instruction;
// ID Stuff
reg [0:1]ControlWB;
reg [0:2]ControlM;
reg [0:3]ControlEX;
reg [0:31]SignExtend;
reg [0:31]Instruction_ID;
reg [0:15]pc_ID;
// EX Stuff
reg [0:4]RegDst;
reg [0:31]readData2Out;
reg [0:31]ALUresult;
reg [0:31]AddResult;
reg Zero;
reg [0:2]ControlM_EX;
reg [0:1]ControlWB_EX;
reg [0:3]ControlEX_EX;
reg [0:31]SignEX;
reg [0:15]pc_EX;
reg [0:31]Instruction_EX;
reg [0:31]readData1_EX;
reg [0:31]readData2_EX;
// MEM Stuff
reg [0:2]ControlM_MEM;
reg [0:1]ControlWB_MEM;
reg [0:31]dmAddress;
reg [0:31]writeData;
// WB Stuff
reg [0:31]wbData0;
reg [0:31]wbData1;
reg RegWrite;
reg [0:31]WriteData;
// Sub Modules
InstructionMem im(clk, pc, Instruction);
Register regMain(clk,Instruction_ID, Instruction_ID, RegWrite, writeData,writeReg,readData1,readData2);
DataMem dm(clk,dmAddress,writeData,ControlM_MEM[0],ControlM_MEM[1],ReadData);
/*initial begin
pc = 0;
PCSrc = 0;
add = 0;
end*/
//always begin
// #5 clk = ~clk;
//end
// IF Stage
assign Instruction = Instruction_ID;
always #(posedge clk) begin
case(PCSrc)
1'b0: pc = add;
1'b1: pc = jump;
default: pc = add;
endcase
add = add + 3'b100;
pc_ID = add;
end
// end IF
// ID begin
always #(posedge clk) begin
casez(Instruction_ID) // Case for determining control values
32'b000000zzzzzzzzzzzzzzzzzzzzzzzzzz: begin // R-Type
ControlWB = 2'b01;
ControlM = 3'b000;
ControlEX = 4'b0101;
end
32'b000100zzzzzzzzzzzzzzzzzzzzzzzzzz: begin // BEQ
ControlWB = 2'bz0;
ControlM = 3'b001;
ControlEX = 4'b001x;
end
32'b100011zzzzzzzzzzzzzzzzzzzzzzzzzz: begin // LW
ControlWB = 2'b11;
ControlM = 3'b100;
ControlEX = 4'b1000;
end
32'b101011zzzzzzzzzzzzzzzzzzzzzzzzzz: begin // SW
ControlWB = 2'bz0;
ControlM = 3'b010;
ControlEX = 4'b100x;
end
endcase
if (Instruction_ID[15] == 0) SignExtend = Instruction_ID & 32'b00000000000000001111111111111111;
else SignExtend = Instruction_ID | 32'b11111111111111110000000000000000;
ControlWB_EX = ControlWB;
ControlM_EX = ControlM;
ControlEX_EX = ControlEX;
SignEX = SignExtend;
pc_EX = pc_ID;
Instruction_EX = Instruction_ID;
readData1_EX = readData1;
readData2_EX = readData2;
end
// ID end
// EX begin
always #(posedge clk) begin
casez(ControlEX_EX)
4'bz00z: ALUresult = readData1_EX + SignExtend;// LW/SW
4'bz01z: if (readData1_EX == readData2_EX)// BEQ
Zero = 1;
else
Zero = 0;
4'bz1zz: begin // R-Type
casez(SignEX)
32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzz0000: ALUresult = readData1_EX + readData2_EX;
32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzz0010: ALUresult = readData2_EX - readData1_EX;
32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzz0100: ALUresult = readData1_EX & readData2_EX;
32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzz0101: ALUresult = readData1_EX | readData2_EX;
32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzz1010: begin
if (readData1_EX < readData2_EX)
ALUresult = 1;
else
ALUresult = 0;
end
endcase
end
endcase
casez(ControlEX_EX)
4'bzzz0: RegDst = Instruction [16:20];
4'bzzz1: RegDst = Instruction [11:15];
endcase
AddResult = pc_EX + (SignEX * 4);
readData2Out = readData2;
ControlM_MEM = ControlM_EX;
ControlWB_MEM = ControlWB_EX;
jump = AddResult;
dmAddress = ALUresult;
writeData = readData2_EX;
end
// EX end
// MEM begin
always #(posedge clk) begin
if (ControlM_MEM == 3'bxx1 && Zero == 1) begin
PCSrc = 1'b1;
end
wbData1 = dmAddress;
wbData0 = ReadData;
end
// MEM end
// WB begin
always #(posedge clk) begin
casez(ControlWB)
2'b0z: WriteData = wbData0;
2'b1z: WriteData = wbData1;
endcase
RegWrite = ControlWB[1];
end
// WB end
endmodule
Test Bench:
module Processor_tf;
// Outputs
reg [0:15] pc;
wire [0:31] Instruction;
reg clk,PCSrc;
reg [0:15]add;
// Instantiate the Unit Under Test (UUT)
Processor uut (
.pc(pc),
.Instruction(Instruction),
.clk(clk)
);
initial begin
// Initialize Inputs
clk = 0;
pc = 16'b0;
PCSrc = 0;
add = 16'b100;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always begin
#5 clk = ~clk;
end
endmodule

With no clk attached to the module Processor, actually your logic is not exercised anyhow.
You have defined clk as output from the Processor whereas it is not being generated inside module. clk is generated inside testbench. So in short :-
Module has no clock as clk is not generated.
Testbecn is generating clkwhich is not connected anywhere.
Define clk as input in Processor and attach clock from testbench to it.

Related

Register file not reading any data

I am trying to design a state machine that counts through and replaces values between 47 and 58. In my waveform though, I keep getting XXX for my R_data in the register file, and thus the rest of my top level design is thrown off. I can't seem to find a reason as to why R_data is outputting XXX for any address with R_en = 1. I'm on Vivado 2020.2; thank you for any help, and please let me know if I need to clarify anything.
Register:
`timescale 1ns / 1ps
module RegFile16x8(R_Addr, W_Addr, R_en, W_en, R_Data, W_Data, Clk, Rst);
input [3:0] R_Addr, W_Addr;
input Clk, Rst, R_en, W_en;
output reg [7:0] R_Data;
input [7:0] W_Data;
reg [7:0] RegFile [0:15];
always #(posedge Clk) begin
if (Rst == 1) begin
RegFile[0] <= 8'd48;
RegFile[1] <= 8'd53;
RegFile[2] <= 8'd68;
RegFile[3] <= 8'd57;
RegFile[4] <= 8'd55;
RegFile[5] <= 8'd59;
RegFile[6] <= 8'd40;
RegFile[7] <= 8'd49;
RegFile[8] <= 8'd31;
RegFile[9] <= 8'd38;
RegFile[10] <= 8'd54;
RegFile[11] <= 8'd50;
RegFile[12] <= 8'd63;
RegFile[13] <= 8'd58;
RegFile[14] <= 8'd70;
RegFile[15] <= 8'd51;
end
else if (W_en==1) begin
RegFile[W_Addr] <= W_Data;
end
end
always #(*) begin
if (R_en==1)
R_Data <= RegFile[R_Addr];
else
R_Data <= 8'bZZZZZZZZ;
end
endmodule
Top Level:
`timescale 1ns / 1ps
module PartA(Clk, Rst, go, done, count);
input Clk, Rst, go;
output reg [6:0] count;
output reg done;
reg [2:0] State, StateNext;
parameter s1 = 0, s2 = 1, s3 = 2, s4 = 3, s5 = 4, s6 = 5, s7 = 6, s8 = 7;
reg [4:0] i;
reg [7:0] temp;
reg R_en, W_en;
reg [7 :0] a_i;
wire [7:0] a_o;
//RegFile16x8(R_Addr, W_Addr, R_en, W_en, R_Data, W_Data, Clk, Rst);
RegFile16x8 r1(i[3:0], i[3:0], R_en, W_en, a_o, a_i, Clk, Rst);
always #(State, Rst, count) begin
R_en = 0;
W_en = 0;
case(State)
s1: begin
if(go == 1)
StateNext = s2;
else
StateNext = s1;
end
s2: begin
done = 0;
count = 0;
i = 0;
StateNext = s3;
end
s3: begin
if(i < 16)
StateNext = s4;
else
StateNext = s5;
end
s4: begin
R_en = 1;
temp = a_o;
if ((temp > 47) && (temp < 58))
StateNext = s7;
else
StateNext = s6;
end
s5: begin
done = 1;
StateNext = s1;
end
s6: begin
StateNext = s8;
end
s7: begin
W_en = 1;
count = count + 1;
a_i = temp - 48;
StateNext = s8;
end
s8: begin
i = i + 1;
StateNext = s3;
end
default: begin
StateNext = s1;
end
endcase
end
always #(posedge Clk) begin
if (Rst == 1)
State = s1;
else
State = StateNext;
end
endmodule
Test Bench:
`timescale 1ns / 1ps
module partA_tb();
reg Clk, Rst, go;
wire [6:0] count;
wire done;
PartA a1(Clk, Rst, go, done, count);
always begin
Clk = 0;
#200
Clk = 1;
#200;
end
initial begin
Rst = 1;
#200
Rst = 0;
go = 1;
end
endmodule
You need to keep Rst in the testbench high for a longer amount of time. The 1st posedge of Clk happens at time 200ns, and that is when you release the reset. You need to keep the reset asserted until after the 1st posedge of the clock in order to properly reset your RegFile, since it is a synchronous reset.
This testbench change allows RegFile to be reset to known values:
initial begin
Rst = 1;
#400
Rst = 0;
go = 1;
end
The change above removes the XXX from R_data.
I chose an arbitrary delay of 400, but it can be anything greater than 200. The key is that you need at least one posedge of Clk to sample Rst when it is high.

Why doesn't the up/down counter count down?

I was doing the Logic Design assignment, and I found some problems I can't solve.
I need to design a 6-bit counter, and this counter needs to count with two functions, for up and down respectively.
I have done the up part and down part, but when I run the simulation, the counting down part doesn't work correctly.
The function for counting down: the next a = a - 2^n, where n = 0, 1, 2, 3... eg. a1 = 63, a2 = 63 - 1 = 62, a3 = 62 - 2 = 60, a4 = 56...
But the simulation with my program, it becomes 63, 62, 61(63 - 2), 59(63 - 4)...
By the way, this assignment has a reset feature.
However, my program won't keep counting after being reset.
It should back to zero and continue counting theoretically.
The following is my code:
`timescale 1ns/100ps
module lab2_1(
input clk,
input rst,
output reg [5:0] out
);
reg [5:0] cnt;
wire [5:0] cnt_next;
reg updown;
wire [5:0] out_next;
initial begin
out = 0;
cnt = 1;
updown = 1;
end
assign cnt_next = (out == 6'b111111) ? 0 : cnt + 1;
assign out_next = out - (2**cnt);
always #(*) begin
if(out == 6'b111111)begin
updown = 0;
end
if(out == 6'b000000)begin
updown = 1;
end
if(rst == 1) begin
out = 0;
updown = 1;
cnt = 0;
end
end
always #(posedge clk, posedge rst) begin
if(updown == 1)begin
if(out > cnt)begin
out <= out - cnt;
end
else
out <= out + cnt;
end
else begin
out <= out_next;
end
cnt <= cnt_next;
end
endmodule
The testbench just monitors the output and drives the inpupts.
`timescale 1ns/100ps
module lab2_1_t;
wire [5:0] out;
reg clk;
reg rst;
lab2_1 v(clk, rst, out);
initial begin
clk = 0;
rst = 0;
$monitor($time,":clk = %b, rst = %b, out = %d", clk, rst, out);
end
always #10 clk = ~clk;
always #10000 rst = ~rst;
endmodule
You should not make assignments to the same signal (such as cnt) from multiple blocks. You can assign to cnt from a single always block. I don't think you need both out and cnt.
Here is a simplified version which automatically switches between up and down:
module lab2_1(
input clk,
input rst,
output reg [5:0] cnt
);
reg updown;
always #(posedge clk, posedge rst) begin
if (rst) begin
updown <= 1;
end else if (cnt == 6'b111110) begin
updown <= 0;
end else if (cnt == 6'b000001) begin
updown <= 1;
end
end
always #(posedge clk, posedge rst) begin
if (rst) begin
cnt <= 0;
end else if (updown) begin
cnt <= cnt + 1;
end else begin
cnt <= cnt - 1;
end
end
endmodule
The code shows a more typical use of the reset signal in the sequential always block. See also for more examples.
Here is a modified testbench where the reset is asserted at time 0, then released after a couple clock cycles. At the end, it asserts reset again so you can see that the counter goes to 0.
module lab2_1_t;
wire [5:0] out;
reg clk;
reg rst;
lab2_1 v(clk, rst, out);
initial begin
$monitor($time,":clk = %b, rst = %b, out = %d", clk, rst, out);
clk = 0;
rst = 1;
#40 rst = 0;
#10000 rst = 1;
#1000 $finish;
end
always #10 clk = ~clk;
endmodule

TestBench I2C Slave SDA won't go low

I'm trying to write an I2C Slave and test it in isolation.
I have a simulation that should be pulling SDA low when write_ack is high (Also highlighted by the red dots). However, you can see that SDA remains the same.
Part of me thinks it's to do with the way I'm testing with the force methods and the delays.
Any help appreciated.
I have found the keyword release which seems to help.
Code below & EDA Playground is here: https://edaplayground.com/x/6snM
/**
I2C Slave to Read/Write 8 bits of data only
*/
`timescale 1ns / 1ps
module Slave(
inout wire SDA,
input wire SCL);
reg [4:0] IDLE = 4'b0000;
reg [4:0] START = 4'b0001;
reg [4:0] READ_ADDRESS = 4'b0010;
reg [4:0] READ_WRITE = 4'b0011;
reg [4:0] DATA = 4'b0100;
reg [4:0] DATA_ACK = 4'b0101;
reg [4:0] STOP = 4'b0110;
reg [4:0] ADDRESS_ACK = 4'b0111;
reg [4:0] state = 4'b0010;
reg [6:0] slaveAddress = 7'b0001000;
reg [7:0] addr;
reg [6:0] addressCounter = 7'b0000000;
reg [7:0] data;
reg [6:0] dataCounter = 7'b0000000;
reg readWrite = 1'b0;
reg start = 0;
reg write_ack = 0;
assign SDA = (write_ack == 1) ? 0 : 'b1z;
always #(negedge SDA) begin
if ((start == 0) && (SCL == 1))
begin
start <= 1;
addressCounter <= 0;
dataCounter <= 0;
end
end
always #(posedge SDA) begin
if (state == DATA_ACK && SCL == 1)
begin
start <= 0;
state <= READ_ADDRESS;
end
end
always #(posedge SCL)
begin
if (start == 1)
begin
case (state)
READ_ADDRESS:
begin
addr[addressCounter] <= SDA;
addressCounter <= addressCounter + 1;
if (addressCounter == 6)
begin
state <= READ_WRITE;
end
end
READ_WRITE:
begin
readWrite <= SDA;
state <= ADDRESS_ACK;
end
ADDRESS_ACK:
begin
write_ack <= 1;
state <= DATA;
end
DATA:
begin
write_ack <= 0;
data[dataCounter] <= SDA;
dataCounter <= dataCounter + 1;
if (dataCounter == 8)
begin
state <= DATA_ACK;
write_ack <= 1;
end
end
DATA_ACK:
begin
write_ack <= 0;
state <= STOP;
end
STOP:
begin
start <= 0;
state <= READ_ADDRESS;
end
endcase
end
end
endmodule
Test Code
/**
Testing I2C Slace for reading/writing 8 bits of data only
*/
`timescale 1ns / 1ps
module Slave_TB ();
reg clk;
wire SDA;
wire SCL;
pullup(SDA);
pullup(SCL);
reg [6:0] addressToSend = 7'b0001000;
reg readWite = 1'b1;
reg [7:0] dataToSend = 8'b01100111;
integer ii=0;
initial begin
clk = 0;
force SCL = clk;
forever begin
clk = #1 ~clk;
force SCL = clk;
end
end
Slave #() UUT
(.SDA(SDA),
.SCL(SCL));
initial
begin
$display("Starting Testbench...");
clk = 0;
force SCL = clk;
#11
// Set SDA Low to start
force SDA = 0;
// Write address
for(ii=0; ii<7; ii=ii+1)
begin
$display("Address SDA %h to %h", SDA, addressToSend[ii]);
#2 force SDA = addressToSend[ii];
end
// Are we wanting to read or write to/from the device?
$display("Read/Write %h SDA: %h", readWite, SDA);
#2 force SDA = readWite;
$display("SDA: %h", SDA);
#2; // Wait for ACK bit
for(ii=0; ii<8; ii=ii+1)
begin
$display("Data SDA %h to %h", SDA, dataToSend[ii]);
#2 force SDA = dataToSend[ii];
end
#2; // Wait for ACK bit
// Force SDA high again, we are done
#2 force SDA = 1;
#100;
$finish();
end
initial
begin
// Required to dump signals to EPWave
$dumpfile("dump.vcd");
$dumpvars(0);
end
endmodule
Instead of using force, a more conventional approach is to add a tristate buffer to the testbench, just like you have in the design.
For SDA, create a buffer control signal (drive_sda) and a testbench data signal (sda_tb). Use a task to drive a byte and wait for the ACK.
Since SCL is not an inout, there is no need for a pullup, and it can be directly driven by clk.
module Slave_TB;
reg clk;
wire SDA;
wire SCL = clk;
pullup(SDA);
reg [6:0] addressToSend = 7'b000_1000; //8
reg readWite = 1'b1; //write
reg [7:0] dataToSend = 8'b0110_0111; //103 = 0x67
reg sda_tb;
reg drive_sda;
assign SDA = (drive_sda) ? sda_tb : 1'bz;
integer ii=0;
initial begin
clk = 0;
forever begin
clk = #1 ~clk;
end
end
Slave UUT
(.SDA(SDA),
.SCL(SCL));
initial begin
$display("Starting Testbench...");
drive_sda = 0;
sda_tb = 1;
#11;
// Set SDA Low to start
drive_sda = 1;
sda_tb = 0;
write({addressToSend, readWite});
write(dataToSend);
// Force SDA high again, we are done
#2;
drive_sda = 1;
sda_tb = 1;
#50;
$finish;
end
task write (reg [7:0] data);
integer ii;
for (ii=7; ii>=0; ii=ii-1) begin
$display("Data SDA %h to %h", SDA, data[ii]);
#2;
drive_sda = 1;
sda_tb = data[ii];
end
#2 drive_sda = 0;
endtask
initial begin
// Required to dump signals to EPWave
$dumpfile("dump.vcd");
$dumpvars(0);
end
endmodule

How can I modify this code? Error is coming out

I'm designing some codes of data bus-system by using ideal SRAM and CPU. I want to write memory mem[0] -> IR, and read memory IR -> mem[1], and finally write memory mem[1] -> DR.
But I'm having some problems.
Here are the codes, and I'm very confusing about making port of input, output, reg, wire. I'm having hard time using 2 DUTs by 1 Testbench. How can I avoid error by modifying this codes?
module sram(addr,clk,din,dout,we);
parameter addr_width = 12, word_depth = 4096, word_width = 16;
input clk,we;
input [addr_width-1:0] addr;
input [word_width-1:0] din;
output [word_width-1:0] dout;
reg [word_width-1:0] mem [0:word_depth-1];
reg [word_width-1:0] dout;
always #(posedge clk) begin
if(!we)
mem[addr] <= din[word_width-1:0];
end
always #(posedge clk) begin
#1 dout <= mem[addr];
end
endmodule
module cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
input clk,reset;
input [1:0]select;
input [1:0]load;
output reg[15:0] ir,dr,ac;
output reg[11:0] ar,pc;
input we;
input [11:0] addr;
reg[15:0] din;
wire[15:0] dout;
sram sram(addr,clk,din,dout,we);
always # (posedge clk or negedge reset) begin
if(!reset) begin
ar <= 12'b0; ir <= 16'b0; pc <= 12'b0; dr <= 16'b0; ac <= 16'b0;
end
if(select==2'b01 && load==2'b01 && we==1)
ir[15:0] <= dout[15:0];
else if(select==2'b01 && load==2'b10 && we==0)
din[15:0] <= ir[15:0];
else if(select==2'b10 && load==2'b01 && we==1)
dr[15:0] <= dout[15:0];
end
endmodule
module tb_cpu();
parameter addr_width = 12, word_depth = 4096, word_width = 16;
reg clk,reset,we;
reg [1:0]select;
reg [1:0]load;
reg [addr_width-1:0] addr;
wire [word_width-1:0] ir,dr,ac;
wire [word_width-5:0] ar,pc;
integer file_pointer;
integer file_pointer2;
cpu cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
always #5 clk = ~clk;
initial begin
clk = 0; addr = 12'b0; we = 0; reset = 1;
#2 reset = 0; #2 reset = 1;
$readmemb("sram.dat", tb_cpu.cpu.sram.mem);
file_pointer = $fopen("reg.dat");
file_pointer2 = $fopen("memory.dat");
#10 select = 2'b01; load = 2'b01; we = 1; addr = 12'b000000000000; //cycle 1
#10 select = 2'b01; load = 2'b10; we = 0; addr = 12'b000000000001; //cycle 2
#10 select = 2'b10; load = 2'b01; we = 1; addr = 12'b000000000001; //cycle 3
$fdisplay(file_pointer, "AR = %b", tb_cpu.cpu.ar);
$fdisplay(file_pointer, "IR = %b", tb_cpu.cpu.ir);
$fdisplay(file_pointer, "PC = %b", tb_cpu.cpu.pc);
$fdisplay(file_pointer, "DR = %b", tb_cpu.cpu.dr);
$fdisplay(file_pointer, "AC = %b", tb_cpu.cpu.ac);
$fdisplay(file_pointer2, "mem[0000 0000 0000] = %b",tb_cpu.cpu.sram.mem[000000000000]);
$fdisplay(file_pointer2, "mem[0000 0000 0001] = %b",tb_cpu.cpu.sram.mem[000000000001]);
$fdisplay(file_pointer2, "mem[0000 0000 0010] = %b",tb_cpu.cpu.sram.mem[000000000010]);
$fclose(file_pointer);
$fclose(file_pointer2);
#10 $finish;
end
endmodule
I get compile errors for your code in the tb_cpu module regarding the tb_cpu.sram hierarchical specifier. You should change all:
tb_cpu.sram
to:
tb_cpu.cpu.sram
For example, change:
$readmemb("sram.dat", tb_cpu.sram.mem);
to:
$readmemb("sram.dat", tb_cpu.cpu.sram.mem);
After I fix those compile errors, I also see compile warnings related to addr and we. I think you need to add addr and we input ports to the cpu module, with proper connections.
Module cpu:
module cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
parameter addr_width = 12, word_depth = 4096, word_width = 16;
input we;
input [addr_width-1:0] addr;
Module tb_cpu:
cpu cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);

Verilog accumulation code error

I am having a problem with accumulator code in Verilog. I simply generate pseudo random signals. Then, change the random signal level -1 to 1 from 0 to 1 so it is signed. Later, obtained 'acmin'. In this point, I need to accumulate 'acmin' signals. Debugger doesn't give me any error but I can't see any result. Can you help me to find problem?
module lfsr(clk, rst, seed, load, R, acc);
input [3:0] R;
input [26:0] seed;
input load;
input rst;
input clk;
reg [3:0]q;
wire [3:0] S;
wire overflow;
wire [3:0] acmin ;
wire [26:0] state_out;
wire [26:0] state_in;
output [7:0] acc;
reg [7:0] acc;
flipflop F[26:0] (state_out, clk, rst, state_in);
mux M1[26:0] (state_in, load, seed, {state_out[25],state_out[24],state_out[23],state_out[22],state_out[21],state_out[20],state_out[19],state_out[18],state_out[17],state_out[16],state_out[15],state_out[14],state_out[13],state_out[12],state_out[11],state_out[10],state_out[9],state_out[8],state_out[7],state_out[6],state_out[5],state_out[4],state_out[3],state_out[2], state_out[1], state_out[0], nextbit});
xor G1(nextbit, state_out[5], state_out[2], state_out[1], state_out[26]);
// Pseudorandom generator
always#(clk) begin
if (state_out[26]==0)
q=4'b1111; // 0 to -1
else
q=4'b0001; //1 to 1
end
assign acmin= R*q; // accumulator input
always#(clk) begin
if(rst)
acc = 8'b00000000;
else
acc = acc + acmin;
end
endmodule
Test bench;
module lfsrtst;
reg [3:0] R;
reg clk;
reg rst;
reg [26:0] seed;
reg load;
wire [7:0] acc;
lfsr lfsr(clk, rst, seed, load, R, acc);
initial
begin
clk = 0;
load = 0;
seed = 0;
rst = 0;
R=0;
#10 rst = 1;
#10 rst = 0;
#50 R = 4'b0111;
#50 R = 4'b0010;
#100 R = 4'b1111;
#50 R = 4'b1011;
#150 R = 4'b1101;
#50 R = 4'b1000;
end
// drive clock
always
#50 clk = !clk;
// program lfsr
initial begin
#100 seed = 27'b000000110000011000001000001;
load = 1;
#100 load = 0;
#1400 $stop;
end
endmodule
I have 'acmin' as I desired. I want to accumulate 'acmin' variable every time the edge of the clock rises and falls. However, 'acc' results nothing so what is the error?
Thanks.
The main problem that I see is that you have a synchronous reset:
always#(clk) begin
if(rst)
acc = 8'b00000000;
else
acc = acc + acmin;
end
But in your testbench you only strobe the reset for #20
#10 rst = 1;
#10 rst = 0;
This is too short, and the reset is never detected.
If you make these delays longer, then the problem should be fixed.
#100 rst = 1;
#100 rst = 0;
// then later
// program lfsr
initial begin
# also delay this so that it comes after the reset
#300 seed = 27'b000000110000011000001000001;
Alternatively you could make the reset asynchronous.
always#(clk or posedge rst) begin
I would try imply a flip-flop here by adding the posedge and converting to '<='
always#(posedge clk) begin
if(rst)
acc <= 8'b00000000;
else
acc <= acc + acmin;
end

Resources