How to fix my current MIPS 32 SCP Register File's clock/data errors - verilog

I'm building a Single Cycle Processor for a class assignment in Verilog and I can't seem to get the correct output with my test bench. I've got everything wired correctly and it is producing zeros for the first half of my test bench like it should, but once I start putting data in, it stays at zero. So I know my reset and clock works, but somewhere in the write section, I am overlooking something. I could use a fresh set of eyes and any help is appreciated. TIA.
RegisterFile.v:
module registerfile(read1, read2, writeto, writedat, writeenable, out1, out2, clock, reset);
input [4:0] read1;
input [4:0] read2;
input [4:0] writeto;
input [31:0] writedat;
input writeenable, clock, reset;
output [31:0] out1, out2;
// 32 bit registers x 32
reg [31:0] RF[31:0];
reg [31:0] out1;
reg [31:0] out2;
integer i;
always #(posedge reset)
begin
for (i = 0; i < 32; i++)
RF[i] <= 0;
out1 <= 32'h00000000;
out2 <= 32'h00000000;
end
always #(posedge clock)
begin
if (writeenable)
RF[writeto] <= writedat;
out1 <= RF[read1];
out2 <= RF[read2];
end
endmodule
RegisterFile_tb.v:
module registerfile_tb ();
reg [4:0] read1;
reg [4:0] read2;
wire [31:0] out1;
wire [31:0] out2;
reg [4:0] writeto;
reg [31:0] writedat;
reg writeenable;
reg clock;
reg reset;
registerfile DUT(read1, read2, writeto, writedat, writeenable, out1, out2, clock, reset);
initial
begin
clock <= 1;
reset <= 1;
#21 reset <= 0;
#100;
read1 <= 5'b0;
read2 <= 5'b0;
writeto <= 5'b00101;
writedat <= 32'd0;
writeenable <= 1;
#100;
#21 read1 <= 5'b11010;
#21 read2 <= 5'b00101;
#21 read1 <= 5'b00001;
#21 writedat <= 32'd1; //
#21 read2 <= 5'b11111;
#21 read1 <= 5'b01010;
#21 read2 <= 5'b01110;
end
always #(read1 or read2)
#21 $display("| read1 = %d | read2 = %d | out1 = %d | out2 = %d |", read1, read2, out1, out2);
endmodule

Your clock is not toggling. There should be an always #10 clk = !clk; in your test bench (you may want a different delay).
Your display statement is a bit odd. Consider changing it to a monitor and move it near the top of the initial block.
FYI. Your code will not synthesis. To me synthesizable a register must be assigned by only one always block. You have separate blocks for the clock and reset. To have asynchronous reset use the structure below. For synchronous reset (required for most FPGAs) then omit the or posedge reset
always #(posedge clock or posedge reset)
begin
if (reset) begin
for (i = 0; i < 32; i++)
RF[i] <= 0;
out1 <= 32'h00000000;
out2 <= 32'h00000000;
end
else begin
if (writeenable)
RF[writeto] <= writedat;
out1 <= RF[read1];
out2 <= RF[read2];
end
end

Related

Why do I get red color for some signals in simulation?

I want to do manchester encoder's simulation in verilog. Design code and testbench codes are written. Although I don't get any error, in the simulation part "clk" and "data_out" are not working which is red color in simulation but reset and data_in are working in the simulation properly. How can I correct the issue?
module manchester_encoder(clk,reset,data_in,data_out);
input clk;
input reset;
input data_in;
output data_out;
integer prev_data;
assign data_out = data_in ^ prev_data;
always #(posedge clk) begin
if (reset) begin
prev_data <= 0;
end else begin
prev_data <= data_in;
end
end
endmodule
Its testbench
module testbench_manchester_encoder();
// Declare the signals
reg clk;
reg reset;
reg data_in;
wire data_out;
// Instantiate the DUT
manchester_encoder encoder(.clk(clk), .reset(reset), .data_in(data_in), .data_out(data_out));
// Generate the clock signal
always #10 clk = ~clk;
// Stimulus process
initial begin
reset = 1;
data_in = 0;
#20 reset = 0;
#10 data_in = 1;
#10 data_in = 0;
#10 data_in = 1;
#10 data_in = 0;
#10 $finish;
end
// Monitor process
always #(posedge clk) begin
$display("Time=%t, data_out=%b", $time, data_out);
end
endmodule
You never initialize clk in your testbench, doing that fixes your problem:
module testbench_manchester_encoder();
// Declare the signals
reg clk = 0; // <------- here
reg reset;
reg data_in;
...

Clock Divider for 50MHz to 1MHz - Verilog

I have written the code for SPI Master and I want the output SPI frequency to be 1MHz.
But, when I run the behaviroal simulation, I don't get a 1MHz spi_sclk. Any suggestions what is wrong with my code? Thanks!
module spi_master(
input wire clk,
input wire reset,
input wire [15:0] datain,
output wire spi_cs_l,
output wire spi_sclk,
output wire spi_data,
output wire [4:0] counter
);
reg [15:0] MOSI;
reg [4:0] count;
reg cs_l;
reg sclk = 1'b0;
reg [2:0] state;
reg [4:0] clk_counter = 0;
// SPI Output Clock frequency = 1MHz
always #(posedge clk) begin
if (clk_counter == 24) begin
clk_counter <= 0;
sclk <= ~sclk;
end
else begin
clk_counter <= clk_counter + 1'd1;
end
end
always #(posedge clk or posedge reset) begin
if(reset) begin
MOSI <= 16'b0;
count <= 5'd16;
cs_l <= 1'b1;
end
else begin
case (state)
0:begin
cs_l <= 1'b1;
state <= 1;
end
1:begin
cs_l <= 1'b0;
MOSI <= datain[count-1];
count <= count-1;
state <= 2;
end
2:begin
if(count > 0) begin
state <= 1;
end
else begin
count <= 16;
state <= 0;
end
end
default:state<=0;
endcase
end
end
assign spi_cs_l = cs_l;
assign spi_sclk = sclk;
assign spi_data = MOSI;
assign counter = count;
endmodule
Testbench
module spi_master_tb;
// Inputs
reg clk;
reg reset;
reg [15:0] datain;
// Outputs
wire spi_cs_l;
wire spi_sclk;
wire spi_data;
wire [4:0] counter;
spi_master dut(
.clk(clk),
.reset(reset),
.counter(counter),
.datain(datain),
.spi_cs_l(spi_cs_l),
.spi_sclk(spi_sclk),
.spi_data(spi_data)
);
initial begin
clk = 0;
reset = 1;
datain = 0;
end
always #5 clk=~clk;
initial begin
#10 reset = 1'b0;
#10 datain = 16'hA569;
#335 datain = 16'h2563;
#335 datain = 16'h9B63;
#335 datain = 16'h6A61;
end
endmodule
Waveform
It helps if you create Minimal reproducible example. Also your waveform don't include an important signal clk_counter.
Try this in your testbench, if it doesn't work you at least have the minimum reproducible example.
I changed the initialization of clk_counter and in the increment I simply added 1 instead of 1'b1, if you wanted to be strict you could add a 5-bit wide 1 (5'b1).
module spi_master(
input wire clk,
input wire reset,
output wire spi_sclk,
);
reg [4:0] clk_counter;
// SPI Output Clock frequency = 1MHz
always #(posedge clk) begin
if(reset) begin
sclk <= 1'b0;
clk_counter <= 1;
end
else begin
if (clk_counter == 24) begin
clk_counter <= 0;
sclk <= ~sclk;
end
else begin
clk_counter <= clk_counter + 1;
end
end
end
assign spi_sclk = sclk;
endmodule

Designing cpu but Value isn't moving in verilog

module sram(addr,clk,din,dout,we); //sram.v
parameter addr_width = 12, word_depth = 110, 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
if(we)
dout[word_width-1:0] <= mem[addr];
end
endmodule
module cpu(clk,reset); //cpu.v
input clk, reset;
reg [15:0] dr, ac, ir;
reg [11:0] addr, pc;
reg [2:0] opcode;
reg [5:0]t;
reg we;
reg sc;
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
ir <= 16'd0; dr <= 16'd0; ac <= 16'd0; addr <= 12'd0; pc <= 12'd0; sc <= 0; t <= 0; we<=1;
end
else if(t==0) begin
addr <= pc; sc<=1;
end
else if(t==1) begin
ir[15:0] <= dout[addr]; pc <= pc+1;
end
else if(t==2) begin
opcode <= ir[14:12];
addr <= ir[11:0]; //no indirect mode, no i
sc<=0;
end
else if(t==3) begin
if(opcode==3'b111) begin
ac <= 0;
end
if(opcode==3'b000) begin
end
end
end
always # (negedge clk) begin
if(!sc) begin
t<=0;
end
else t<=t+1;
end
endmodule
module tbcpu(); //tbcpu.v
reg clk,reset;
integer file_pointer;
cpu cpu(clk,reset);
always #5 clk = ~clk;
initial begin
$readmemb("memory.dat", tbcpu.cpu.sram.mem); //assembly
clk = 0; reset = 1;
#1 reset = 0;
#1 reset = 1;
#100 $finish;
end
endmodule
I'm designing cpu and having hard time because ir[15:0] value doesn't change and fixed in 0000.
I'm expecting when t comes 01 (in 15ns),
this conditional sentence work :
else if(t==1) begin
ir[15:0] <= dout[addr]; pc <= pc+1;
so dout[0] value 7800 go into ir[15:0], but it doesn't work. How can I fix this? I'm also confusing about sc, t timing so I solved that problem by changing sc,t values in negedge clk.
Change:
ir[15:0] <= dout[addr];
to:
ir[15:0] <= dout;
dout[addr] selects a single bit of the 16-bit dout signal. You were treating dout as if it were a memory variable, instead of a vector signal. At 15ns, dout='h7800 and addr=0, which means ir=dout[addr]=dout[0]=0.

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

Verilog: one clock cycle delay using register

I'm trying to delay two signals. I wrote a register to do that and instantiated it but a strange thing happens. Delaying "state" signal seems to work, but delaying "nb_bits" signal doesn't.
Here's my code for the register:
`timescale 1ns / 1ps
module register(
input CLK,
input clr,
input en,
input [7:0] in,
output [7:0] out
);
reg [7:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 8'b00010000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And that's ma instantiation:
wire [3:0] nbb;
nb_bits_register nb_bits_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(nb_bits),
.out(nbb)
);
wire [7:0] stt;
register state_reg(
.CLK(CLK),
.clr(clr),
.en(en),
.in(state),
.out(stt)
);
nb_bits_register module is analogical; I didn't want to parametrize before solving this problem.
`timescale 1ns / 1ps
module nb_bits_register(
input CLK,
input clr,
input en,
input [3:0] in,
output [3:0] out
);
reg [3:0] temp;
always # (posedge CLK or posedge clr) begin
if (clr) begin
temp <= 4'b0000;
end
else if (en) begin
temp <= in;
end
else begin
temp <= temp;
end
end
assign out = temp;
endmodule
And here's a simulation:
enter image description here
And testbench:
`timescale 1ns / 1ps
module state_machine_tb();
reg CLK, clr, en;
reg [7:0] symbol;
reg [3:0] nb_bits;
wire [7:0] state;
initial begin
CLK <= 1;
clr <= 0;
en <= 0;
symbol <= 8'b00110010;
nb_bits <= 1;
#10
clr <= 1;
en <= 1;
#10
clr <= 0;
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110010;
nb_bits <= 2;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110001;
nb_bits <= 1;
#10
symbol <= 8'b00110000;
nb_bits <= 3;
#10
$finish;
end
always begin
#5 CLK <= ~CLK;
end
state_machine state_machine_inst(
.CLK(CLK),
.clr(clr),
.en(en),
.symbol(symbol),
.nb_bits(nb_bits),
.state(state)
);
endmodule
It does seem like a rase condition in the scheduler. By definition from the Verilog LRM, the order of evaluating procedural blocks (always blocks and initial blocks) is indeterminate. You might notice a pattern with a particular simulator and version, but that patter can change when changing the simulator or changing the version of the same simulator.
Use blocking assignment with your clock (ex: always #5 CLK = ~CLK;). With will guarantee the CLK will be updated before other stimulus.
In the test bench, change all the #10 to #(posedge CLK). The timing will be the same, however it guarantees CLK was updated before evaluating the new values symbol and other stimulus.
FYI: If you change output [7:0] out to output reg [7:0] out you can assign out directly in your always block, removing the need for temp. This doesn't change anything functionally; just fewer variables and lines of code.
It seems like a race condition: your changes of nb_bits coincide with positive edges of CLK, so there's an ambiguity resolved by the simulator in this way:
change nb_bits (from 1 to 2, etc.)
change CLK from 0 to 1
execute in nb_bits_register: if (en) temp <= in; ... assign out = temp;
As the result, out = in in nb_bits_register.
A solution is to avoid this coincidence, e.g. by changing the first #10 in the testbench to #11.

Resources