I tried to make a CMP instruction in Verilog. To keep the result of the substraction, I declared a wire. This is what the code looks like (It is executed in an always statement).
wire [data_width:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
Now Icarus Verilog complains about a syntax error and that reg_accumulator - reg_x is not an l-value:
cpu.v:149: syntax error
cpu.v:149: Syntax in assignment statement l-value.
And why does it complain? What would be the right approach to declare a temporary variable in a function / task?
module comparator(
input clk,
input [7:0] op_a,
input [7:0] op_b
);
reg f_zero;
reg f_carry;
function compare;
input [data_width-1:0] a;
input [data_width-1:0] b;
begin
wire [7:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end
endfunction
always #(posedge clk) begin
compare(op_a, op_b);
end
endmodule // comparator
Either you should use systemverilog and include this in a class or you can create a parameterized module:
module compare_zero_n_carry
# (
parameter DATA_WIDTH = 8
)
(zero, carry, a, b);
/* ports */
input [DATA_WIDTH-1:0] a; //.."reg_accumulator"
input [DATA_WIDTH-1:0] b; //.."reg_x"
output zero;
output carry;
wire [DATA_WIDTH-1:0] tmp_wire = a - b;
assign zero = (tmp_wire & {DATA_WIDTH{1'b1}}) == {DATA_WIDTH{1'b0}};
//..HERE IM NOT REALLY SURE WHAT IS THE LOGIC FOR THE CARRY,
//..IT SHOULD BE ONE BIT
assign carry = (tmp_wire & {1'b1,{(DATA_WIDTH-1){1'b0}}});
endmodule // compare_zero_n_carry
And instantiate it in the main comparator module as:
input clk;
input [DATA_WIDTH-1:0] op_a;
input [DATA_WIDTH-1:0] op_b;
wire f_zero;
wire f_carry;
reg f_zero_reg;
reg f_carry_reg;
compare_zero_n_carry
# (
.DATA_WIDTH (DATA_WIDTH)
)
compare_zero_n_carry_inst (
.a (op_a),
.b (op_b),
.zero (f_zero),
.carry (f_carry)
);
always # (posedge clk) begin
f_zero_reg <= f_zero;
f_carry_reg <= f_carry;
end
You cannot declare a wire inside the always block.
wire [7:0] tmp_wire = reg_accumulator - reg_x;
always #(posedge clk) begin
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end
Related
I am trying to delay a 32-bit signal using shift register. My logic is a single flip flop delay a signal by 1 clk so I use shift register as it is combination of flip flop can someone guide me what is wrong with this code.
module delay_n_cycles (
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out,
parameter N = 5
);
reg [31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= {shift_reg[30:0], data_in};
if (N == 0) begin
data_out <= shift_reg[31];
end else begin
data_out <= shift_reg[N-1];
end
end
endmodule
First of all, your code is syntactically wrong. parameter cannot be declared in a way you provided.
Your shift register is only 32 bit wide. Usually, to delay multi-bit data this way, you need to keep N copies of data in the register, shift them at one end and read at the other. I guess the following should help:
module delay_n_cycles #(parameter N = 5)(
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out
);
reg [N-1:0][31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= (shift_reg << 32) | data_in;
data_out <= shift_reg[N-1];
end
endmodule
This code will work with system verilog because it used packed multi-dimensional arrays.
You need to shift the reg by 32 (width of the data) in packed version.
Here is an example of a testbench:
module tb();
bit clk;
int clkCount;
initial
forever begin
#5 clk = ~clk;
clkCount++;
end
logic [31:0] data_in, data_out;
initial begin
$monitor("%0t (%0d) [%h]: %0d --> %0d", $time, clkCount, ds.shift_reg[4], data_in, ds.data_out);
for(int i = 0; i < 20; i++) begin
#10 data_in = i;
end
$finish;
end
delay_n_cycles ds(data_in, clk, data_out);
endmodule
This question already has answers here:
How do I use flip flop output as input for reset signal
(1 answer)
Why is my counter out value producing StX?
(2 answers)
Closed 2 months ago.
Trying to make a Binary adder and Subtractor in Verilog Output keeps coming out as X I don't think it is the testbench I believe is something wrong with the wires for the output F. The Flip Flops and the Multiplexer should be correct but I have no way of knowing for sure I do not get any error messages when I run this
module Subtractor(A, B, Bin, Bout , Sub); //Variables for subtractor
// 1-bit full binary subtractor.
input A;//Input variable
input B;//Input variable
input Bin;//Input variable
output Bout;
output Sub;
assign Bout=((~A)&(B))|((~A)&(Bin))|((B)&(Bin));
assign Sub=(A^B^Bin);
endmodule
module Adder(A, B, Cin, Cout, Sum);
// 1- bit full binary adder
input A, B, Cin;
output Cout, Sum;
assign Cout = ((A)&(Cin))|((B)&(Cin))|((A)&(B));
assign Sum = (A^B^Cin);
endmodule
module CarryFLIPFLOP(CLK,RESET,D,Q);
//Flip flop for carry value
input CLK,RESET,D;
output reg Q;
always #(posedge CLK)
begin
if(RESET)
Q<=0;
else
Q<=D;
end
endmodule
module BorrowFLIPFLOP(CLK,RESET,D,Q);
// 1- bit full binary adder
input CLK,RESET,D;
output reg Q;
//reg Q;
always #(posedge CLK)
begin
if(RESET)
Q<=0;
else
Q<=D;
end
endmodule
module Fplexer(Sum, Sub, S, F, clk);
input Sum, Sub, S, clk;
output reg F;
always#(posedge clk) begin
if(S==1) begin
F <= Sum;
end else begin
F <= Sub;
end
end
endmodule
module z_flag(clk,F,R,Z);
input clk,F,R;
output reg Z=1;
always#(posedge clk)begin
Z=R|(Z&~F);
end
endmodule
module top(A,B,S,R,clk,F,Z,N,V);
input A, B, S, R, clk;
output F, Z, N, V;
wire w0,w1,w2,w3,w4,w5,w6,w7,w8;
assign w7 = A;
assign w8 = B;
Subtractor S0(.A(w7), .B(w8), .Bin(w3), .Bout(w4), .Sub(w5));
BorrowFLIPFLOP Borrow(.CLK(clk), .RESET(R), .D(w2), .Q(w3));
Adder A0(.A(w7), .B(w8), .Cin(w0), .Cout(w1), .Sum(w2));
CarryFLIPFLOP Carry(.CLK(clk), .RESET(R), .D(w2), .Q(w0));
Fplexer multi(.Sum(w2), .Sub(w5), .S(S), .F(w6), .clk(clk));
assign V=(w0 & w1);
assign F = w6;
assign N = w6;
z_flag Zflag(.clk(clk), .F(w6), .R(R), .Z(Z));
endmodule
module testbench;
reg clk;
reg R;
reg A;
reg B;
reg S = 0;
wire F;
//intitialize clock/top
top UUT(A,B,S,R,clk,F,Z,N,V);
always
#5 clk = ~clk;
initial begin
$display("Testing +- Machine");
$monitor("%d - %d Is %d",A, B, F);
A = 0; B = 1; S = 0; R=0; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
A = 1; B = 1; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
A = 1; B = 0; #10;
clk = 1; #1;
clk = 0; #1;
clk = 1; #1;
end
endmodule
Your design has a reset signal and you never used it.
Your FLIPFLOP code does not have RESET in the sensitivity list.
You are making assignments to clk in an always block and in the initial block. Pick one place.
Learn how to save waveforms to see internal signals, not just the top level output.
I'm writing an ALU for a processor I'm designing (first RTL project) and I'm getting a high impedance output on ALU_out when I run my testbench, even though the flags do get set and are output correctly.
module alu(
input clk,
input reset,
input [7:0] A, B,
input [3:0] Op_Sel,
output [7:0] ALU_out,
output C, V, N, Z
);
reg [8:0] Result = 0;
reg [8:0] cn_temp = 0;
reg [7:0] v_temp = 0;
reg carry = 0;
reg overflow = 0;
reg negative = 0;
reg zero = 0;
assign ALU_Out = Result[7:0];
assign C = carry;
assign V = overflow;
assign N = negative;
assign Z = zero;
always #*
begin
if (reset)
begin
Result = 0;
cn_temp = 0;
v_temp = 0;
carry = 0;
overflow = 0;
negative = 0;
zero = 0;
end
end
always #(posedge clk)
begin
case(Op_Sel)
4'b0000: // Addition
begin
Result = A + B;
negative = Result[7];
zero = (Result[7:0] == 8'b00000000);
carry = Result[8];
v_temp = A[6:0] + B[6:0];
overflow = v_temp[7] ^ carry;
end
.
.
//The rest of the instructions
.
.
.
endcase
end
endmodule
//My testbench
module alu_testbench();
reg clk;
reg reset;
reg [7:0] A;
reg [7:0] B;
reg [3:0] Op_Sel;
wire [7:0] ALU_out;
wire C, V, N, Z;
always begin
#1
clk = ~clk;
end
initial begin
clk = 0;
reset = 0;
#1
reset = 1;
#1
reset = 0;
end
initial begin
#10
A=2;
B=3;
Op_Sel = 4'b0000;
#10
A=1;
end
alu alu (
.clk(clk),
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
endmodule
I believe I connected up the module to the testbench (through a wire), so why am I getting high impedance on ALU_out?
This was a tricky typo. You mistakenly used an upper-case "O" in the ALU_Out signal name. Since Verilog is case-sensitive, this is a different signal from ALU_out. It is not mandatory to declare all signals in Verilog. However, you can use the following compiler directive in your code to help catch this type of common problem:
`default_nettype none
Your simulator should generate an error.
To fix it, change:
assign ALU_Out = Result[7:0];
to:
assign ALU_out = Result[7:0];
My simulators also generated a warning message because you didn't drive the reset input of alu. Here is the fix:
alu alu (
.clk(clk),
.reset(reset), /// <------ add this
.A(A),
.B(B),
.Op_Sel(Op_Sel),
.ALU_out(ALU_out),
.C(C),
.V(V),
.N(N),
.Z(Z));
I am tasked with building an ALU. However, I must not understand how the self-checking testbench with file.tv should run. I have run other simple testbenches just fine. I am sure there is a problem in the way that my testbench module is written,
code compiles (using quartus)
made a text file with binary and turned it into a "test.tv" file
opened modelsim and added file
when I run it, is has an issue where it just keeps running blue errors..
Here is my code:
module ALU(input [31:0] a,b,
input [2:0] f,
output reg [31:0] y ,
output reg zero);
always #(*) begin
case(f)
3'b000: y = a & b;
3'b001: y = a | b;
3'b010: y = a + b;
3'b011: y = 32'b0;
3'b100: y = a & ~b;
3'b101: y = a | ~b;
3'b110: y = a - b;
3'b111: y = a < b;
default: y = 32'b0;
endcase
if(y==0)
zero=1'b1;
else
zero=1'b0;
end
endmodule
//**********************
module ALUtest();
reg clk;
reg [31:0] a, b, yexpected;
wire [31:0] y;
reg [2:0] f;
reg zeroexpected;
wire zero;
reg [31:0] vectornum, errors;
reg [100:0] testvectors[10000:0];
ALU dut(a,b,f,y,zero);
always
begin
clk = 1; #5; clk = 0; #5;
end
initial
begin
$readmemb("test.tv", testvectors);
vectornum = 0; errors = 0;
end
always#(posedge clk)
begin
#1; {a,b,f, yexpected,zeroexpected} = testvectors[vectornum];
end
always #(negedge clk)
begin
if (y !== yexpected) begin
$display("Error: inputs = %b", {a,b,f});
$display(" outputs = %b (%b expected)", y, yexpected);
errors = errors + 1;
end
vectornum = vectornum + 1;
if (testvectors[vectornum] === 4'bx) begin
$display("%d tests completed with %d errors", vectornum, errors);
$stop;
end
end
endmodule
//*************************************
CONTINUOUS ERROR THAT KEEPS RUNNING UNTIL I STOP IT:
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
Error: inputs = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
outputs = 00000000000000000000000000000000(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx expected)
This is what my "test.tv" file looks like in binary
00000000000000000000000000000000_00000000000000000000000000000000_010_00000000000000000000000000000000_1
00000000000000000000000000000000_11111111111111111111111111111111_010_11111111111111111111111111111111_0
00000000000000000000000000000000_01010101010101010101010101010101_010_01010101010101010101010101010101_0
I know this might seem stupid and simple, but I am really trying to learn this and obviously do not understand something. Can someone please help? Thanks in advance!
testvectors is declared as:
reg [100:0] testvectors[10000:0];
100:0 means testvectors is 101 bits wide, but you are comparing it to a 4-bit value (4'bx is the same as 4'bxxxx).
Change:
if (testvectors[vectornum] === 4'bx) begin
to:
if (testvectors[vectornum] === {101{1'bx}}) begin
This stops for me using your 3-line test.tv file.
Note that the LHS (32*3+3+1) is 100 bits, but the RHS is 101 bits in the following expression:
{a,b,f, yexpected,zeroexpected} = testvectors[vectornum]
Also, you only specify 100 bits in the test.tv file. Perhaps you should declare testvectors as 100 bits wide:
reg [99:0] testvectors[10000:0];
My current task is to create a memory driver. The specific issue is that I have a shift register designed to concatenate four 8-bit words into one 32-bit and then send that to the output. The module works when being simulated by itself but it fails to respond when connected to other modules. Here's the code :
The shift register code :
module shiftReg (
data_8,
clk,
valid1,
rstn,
data_32,
valid_fifo,
count,
REGA,
REGB,
REGC,
REGD
);
input wire [7:0] data_8;
input wire valid1;
input wire clk;
input wire rstn;
output reg [31:0] data_32;
output reg valid_fifo;
output reg [3:0] count;
output reg [7:0] REGA;
output reg [7:0] REGB;
output reg [7:0] REGC;
output reg [7:0] REGD;
initial
begin
count <= 4'b0001;
REGA <= 8'b0;
REGB <= 8'b0;
REGC <= 8'b0;
REGD <= 8'b0;
valid_fifo <= 1'b0;
end
always #(posedge valid1)
begin
if(~rstn)
begin
count = 4'b0001;
REGA = 0;
REGB = 0;
REGC = 0;
REGD = 0;
end
else if(valid1 == 1'b1)
begin
case (count)
4'b0001: REGA = data_8;
4'b0010: REGB = data_8;
4'b0100: REGC = data_8;
4'b1000: REGD = data_8;
endcase
valid_fifo = 1'b0;
end
if(count == 4'b1000)
begin
data_32 = {REGD,REGC,REGB,REGA};
valid_fifo = 1'b1;
count = 4'b0001;
end
else
begin
count = count << 1;
end
end
endmodule
The module where I am instantiating it is called altogether.
Here is the code :
module altogether (
input wire BUTTON_AT,
input wire CLK_AT,
input wire RSTN_AT,
output wire MEM_FULL_AT,
output wire EMPTY_AT,
inout wire VALID_IN_AT,
inout wire [7:0] DATA_8_AT,
inout wire VALID1_AT,
inout wire [31:0] DATA_32_AT,
inout wire STOP_AT,
inout wire VALID_FIFO_AT,
inout wire [31:0] DATA_AT,
inout wire WR_AT,
inout wire [6:0] ADDR_AT,
output wire [7:0] REG_A_AT,
output wire [7:0] REG_B_AT,
output wire [7:0] REG_C_AT,
output wire [7:0] REG_D_AT,
output wire [3:0] COUNT_AT
);
shiftReg shift_register (
.data_8(DATA_8_AT),
.clk(CLK_AT),
.valid1(VALID_1_AT),
.rstn(RSTN_AT),
.data_32(DATA_32_AT),
.valid_fifo(VALID_FIFO_AT),
.REGA(REG_A_AT),
.REGB(REG_B_AT),
.REGC(REG_C_AT),
.REGD(REG_D_AT),
.count(COUNT_AT)
);
For some reason, the valid == 1'b1 condition is not executed when I put the shift register along with everything else. I have really run out of ideas, hope someone manages to look at it and give me an insight.
Somewhere during synthesis you probably got warning that you're using VALID_1_AT signal, which has no driver. That's because in altogether module declaration you define VALID1_AT signal (notice _ missing in signal name). That's why valid1 in your shift register is not driven at all.
You should change:
.valid1(VALID_1_AT)
into:
.valid1(VALID1_AT)
to make it works.