I have a problem in PISO verilog register.
Below is my code
`timescale 1ns / 1ps
module PISO(
input clk,
input load,
input [3:0] d,
output reg Qout);
reg [3 : 0]Q;
always # (posedge clk)
begin
if ( load )
Q <= d;
else
begin
Qout <= d[3];
Q<= { Q[2:0] , 1'b0 };
end
end
endmodule
and my testbench
`timescale 1ns / 1ps
module PISO_tb();
PISO uut(clk,load,d,Qout);
reg clk;
reg load;
reg [3:0]d;
wire Qout;
initial begin
clk=0;
forever #5 clk = ~clk;
end
initial begin
load = 1;
d[0] = 1'b0;
d[1] = 1'b1;
d[2] = 1'b0;
d[3] = 1'b1;
#6 load = 0;
end
endmodule
And it isn't working as it should, please help me with testbench maybe? Because I think the verilog code is okay and it should work properly.
You want the Qout signal to be the output of the shift register (Q) instead of the input, so that the output toggles instead of remaining at 1. Change:
Qout <= d[3];
to:
Qout <= Q[3];
I am testing a module for an 8-bit register, separately from the rest of my code. I am using ModelSim to set the values and then Run to see the results.
This module is supposed to have a binary number input, a clear bit, an enable bit, and an output.
module Register8bit(D, Clk, Clear, Enable, OutNum);
input [7:0] D; //8 bit binary data
input Clk; //Clock
input Clear; //Clear bit
input Enable; //Enable bit
output reg [7:0] OutNum;
always #(posedge Clk)
begin
if (Enable)
begin
if (Clear)
OutNum <= 8'b00000000;
else
OutNum <= D;
end
end
endmodule
Here is the output I am expecting (in this order), with D = 10001111 and Clk = 1.
Steps CLR Enable OutNum
1 0 0 xxxxxxxx (initially undefined)
2 0 1 10001111 (input data is used)
3 1 0 10001111 (because write-protection)
4 1 1 00000000 (Clear and Enable are true, so set to 0)
5 0 1 10001111 (Clear is false and Enable is true, so use input data)
The first step works, but the second one does not (so the rest don't work either). Specifically, OutNum stays undefined on the second step. Updating OutNum with the input data does work in the first step if Enable is true.
How should I fix this module?
Test bench code:
`timescale 1ns / 1ps
module test_register;
//inputs
reg [7:0] D;
reg Clk;
reg Clear;
reg Enable;
//outputs
reg [7:0] OutNum;
//instantiate
Register8bit uut(
.D(D),
.Clk(Clk),
.Clear(Clear),
.Enable(Enable)
);
initial begin
D = 10001111;
Clk = 1;
//step 1
#100;
Clear = 0;
Enable = 0;
#100;
//step 2
Clear = 0;
Enable = 1;
#100;
//step 3
Clear = 1;
Enable = 0;
#100;
//step 4
Clear = 1;
Enable = 1;
#100;
//step 5
Clear = 0;
Enable = 1;
#100;
end
endmodule
You need to toggle your Clk signal many times. Your code just sets it to 1, then leaves it at 1 for the whole sim.
module test_register;
//inputs
reg [7:0] D;
reg Clk;
reg Clear;
reg Enable;
//outputs
reg [7:0] OutNum;
//instantiate
Register8bit uut(
.OutNum (OutNum), // <---- added missing output
.D(D),
.Clk(Clk),
.Clear(Clear),
.Enable(Enable)
);
always #50 Clk = ~Clk;
always #(negedge Clk) begin
$display($time, " clr=%b en=%b D=%b OutNum=%b", Clear, Enable, D, OutNum);
end
initial begin
D = 'b10001111; // <---- use 'b
Clk = 1;
#50;
//step 1
#100;
Clear = 0;
Enable = 0;
#100;
//step 2
Clear = 0;
Enable = 1;
#100;
//step 3
Clear = 1;
Enable = 0;
#100;
//step 4
Clear = 1;
Enable = 1;
#100;
//step 5
Clear = 0;
Enable = 1;
#100;
#500 $finish;
end
endmodule
/*
Prints out:
50 clr=x en=x D=10001111 OutNum=xxxxxxxx
150 clr=0 en=0 D=10001111 OutNum=xxxxxxxx
250 clr=0 en=1 D=10001111 OutNum=xxxxxxxx
350 clr=1 en=0 D=10001111 OutNum=10001111
450 clr=1 en=1 D=10001111 OutNum=10001111
550 clr=0 en=1 D=10001111 OutNum=00000000
650 clr=0 en=1 D=10001111 OutNum=10001111
750 clr=0 en=1 D=10001111 OutNum=10001111
850 clr=0 en=1 D=10001111 OutNum=10001111
950 clr=0 en=1 D=10001111 OutNum=10001111
1050 clr=0 en=1 D=10001111 OutNum=10001111
*/
I am having a small issue here in when I instantiated my modules. I am using a generate loop to create 100 instances of 2 counters (16 & 32 bit counters). Each counter should have their own independent controls (UPDN & EN), but they share a clock and a reset.
Module Descriptions:
SAT_COUNTER.sv // SIMPLE COUNTER MODULE
TWO_SC.sv // INSTANTIATES TWO SAT_COUNTER MODULES (16 BIT & 32 BIT
COUNTERS)
GEN_SC.sv // INSTANTIATES 100 MODULES OF TWO_SC MODULES
tb_GEN_SC.sv // TESTBENCH
I am sure that my problem is in the GEN_SC module where I instantiate all 100..
I appreciate any help! Thank you in advance!
module SAT_COUNTER(
COUNT, // SCALABLE COUNT OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE LOW RESET
UPDN, // COUNTER WILL COUNT: UP = 1; DN = 0;
EN); // ENABLE
parameter WIDTH = 8;
input CLK, al_RST, UPDN, EN;
output reg [WIDTH-1:0] COUNT;
...
endmodule
//**********************
module TWO_SC(
COUNT1, // N-BIT COUNTER OUTPUT
COUNT2, // M-BIT COUNTER OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN, EN;
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
SAT_COUNTER #(WIDTH1) GSC1(.COUNT(COUNT1), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[0]), .EN(EN[0]));
SAT_COUNTER #(WIDTH2) GSC2(.COUNT(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[1]), .EN(EN[1]));
endmodule
//**********************
module GEN_SC(
COUNT1, // COUNT1
COUNT2, // COUNT2
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
genvar j;
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1), .COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
endmodule
//**********************
module tb_GEN_SC();
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
reg CLK, al_RST;
reg [1:0] UPDN [MOD_COUNT-1:0];
reg [1:0] EN [MOD_COUNT-1:0];
wire [WIDTH1-1:0] COUNT1;
wire [WIDTH2-1:0] COUNT2;
GEN_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) UUT(COUNT1, COUNT2, CLK, al_RST, UPDN, EN);
initial begin
CLK = 1'b1;
forever
#5 CLK = ~CLK;
end
initial
$monitorb("%d COUNT = %b (%d) | UPDN = %b | EN = %b | COUNT = %b (%d) | UPDN = %b | EN = %b | al_RST = %b | CLK = %b", $time, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.UPDN[0], UUT.SC[87].TWOCOUNTERS.EN[0], UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.UPDN[0], UUT.SC[99].TWOCOUNTERS.EN[0], al_RST, CLK);
initial begin
$vcdpluson;
UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 0; al_RST = 1;
#10 UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 0; al_RST = 0; // RESET COUNTER
#10 EN = 1; al_RST = 1; // ENABLE COUNTER AND COUNT UP (HITS MAX)
#200 UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 0; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 1; // BEGIN TO COUNT DOWN
#10 EN = 0;
#60 EN = 3;
// #230 UPDN = 1; UPDN = 0;
#3017 al_RST = 0;
#100 al_RST = 1;
#20 $finish;
end
/////////// ERRORS I GET /////////////////
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IUDA] Incompatible dimensions
tb_GEN_SC.sv, 34
Incompatible unpacked dimensions in assignment
Arrays with incompatible unpacked dimensions cannot be used in assignments,
initializations and instantiations.
Error-[ICTA] Incompatible complex type
tb_GEN_SC.sv, 34
Incompatible complex type assignment
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'reg[1:0]$[99:0]', while the type
of the source is 'int'.
Source Expression: 0
You have just one UPDB and one EN port in port list. So how you wana apply different UPDN and EN to instances?
An idea is to define an array with size of MOD_COUNT so that each element has its own control input. then in genvar loop you can use the index. like this:
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
...
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1),
.COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
I have written all the code, including the modules, but I can't figure out how to wire the modules to the main program.
The ALU should be:
A (4bits) and B (4bits) as inputs, sel (3bits)
1st Module When sel = 000 => Add/ sel= 001 => Sub (A+B or A-B)
2nd Module When sel = 010 => Shift right by 1
3rd Module when sel = 011 => Multiply (A*B)
4th Module When sel = 100 => A XNOR B
5th Module When sel = 101 => Compare A==B
I also made a 6th module with a Mux6to1.
It has to be on a gate level. Can't use (+/-). This is the code I've been writing but when I simulate, I just get the result: ZZZZZZZZ. Please, any suggestions would be appreciated, thanks.
For Add/Sub 1 bit:
module Full_Adder_1bit(a,b,cin,sel,sum,cout);
input a, b, cin;
input [2:0] sel;
output sum, cout;
reg sum, cout;
reg a_in;
always # (a or b or cin or sel)
begin
a_in = a^sel[0];
sum = a^b^cin;
cout = (a_in&b)|(a_in&cin)|(b&cin);
end
endmodule
For 4 bit ADD/SUB:
module Full_Adder_4bits (a, b, cin, sel, sum, cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [3:0] sum;
output cout;
wire c1,c2,c3;
Full_Adder_1bit FA0(a[0],b[0],cin,sel,sum[0],c1);
Full_Adder_1bit FA1(a[1],b[1],c1,sel,sum[1],c2);
Full_Adder_1bit FA2(a[2],b[2],c2,sel,sum[2],c3);
Full_Adder_1bit FA3(a[3],b[3],c3,sel,sum[3],cout);
endmodule
For the Shifter:
module Shifter(dataIn, shiftOut);
output [3:0] shiftOut;
input [3:0] dataIn;
assign shiftOut = dataIn >> 1;
endmodule
For the XNOR:
module XNOR(a,b,rxnor);
input [3:0] a,b;
output [3:0] rxnor;
reg rxnor;
always # (a or b)
begin
rxnor= a~^b; //XNOR
end
endmodule
For Multiplier:
module mul4 (i0,i1,prod);
input [3:0] i0, i1;
output [7:0] prod;
assign prod = i0*i1;
endmodule
For Compare:
module Compare(B,A,R);
input [3:0] A,B;
output [3:0] R;
reg R;
always#(A,B)
begin
if (A==B)
R = 4'b0001;
else if (A==B)
R = 4'b0000;
else
R = 4'b1111;
end
endmodule
For the mux (it is actually 5 to 1 even though the name says 6 to 2):
module MUX6to2(i0,i1,i2,i3,i4,sel,out);
input [4:0] i0,i1,i2,i4;
input [7:0] i3;
input [2:0] sel;
output [7:0] out;
reg [7:0] out;
always # (i0 or i1 or i2 or i3 or i4 or sel)
begin
case (sel)
3'b000: out = i0;
3'b001: out = i0;
3'b010: out = i1;
3'b011: out = i2;
3'b100: out = i3;
3'b100: out = i4;
default: out = 8'bx;
endcase
end
endmodule
For the ALU:
module ALU(a,b,cin,sel,r,cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [7:0] r;
output cout;
wire [3:0] add_out, shift_out, xnor_out, compare_out;
wire [7:0] mul_out;
wire cout;
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
Full_Adder_4bits output_adder (a,b,cin,sel [2:0],add_out,cout);
Shifter output_shifter (a,shift_out);
XNOR output_XNOR (a,b,xnor_out);
mul4 output_mul4 (a,b,mul_out);
Compare output_Compare (a,b,compare_out);
endmodule
Why the value of output "r" Hi-Z is you haven't connected anything to output so the default value of wire is propagated in the output
When it comes to your design a decoder is required and for arithmetic operation operand size has to be taken care
Required bit widths are
addition 4 bit + 4 bit = 4 bit + carry,
subtraction 4 bit - 4 bit = 4 bit + borrow,
shifting which of them should be shifted and required bit width needs to be calculated,
multiplication 4*4 bit = 8 bit is needed,
xnor 4 bit xnot 4 bit = 4 bit needed,
compare it is up how we represent if equal with 1 bit or any bit widths
In your Mux logic you have
3'b100: out = i3;
3'b100: out = i4;
Here in this both case items are same so synthesizer optimizes and only considers the first statement and ignores the second, in general case should not be coded this way and more over this mux itself is not necessary.
Coming to your top module ALU, the syntax is wrong, this type of assignments are not permitted in verilog HDL
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
When integrating all modules you have to be clear about what you are going to connect and widths with hardware in mind map,
Considering your design
The adder will result in 4bit + carry but output "r" is 8 bit so other bits should made to constant value or else it will be defaulted to X in case reg or Hi-z in case wire in the output, similar for other operations too.
I have made some modification in the design with a decoder and found to be fully functional,
A (4bits) and B (4bits) as inputs, sel (3bits)
When sel = 000 => Add/ sel= 001 => Sub (A+B or A-B)
When sel = 010 => Shift right by 1
when sel = 011 => Multiply (A*B)
When sel = 100 => A XNOR B
When sel = 101 => Compare A==B
Give a try of the code http://www.edaplayground.com/x/DaF
in the module ALU, check the port list which where mapped to multiplexer module as emman said.
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
in this module, the output which declared is of size 8 bit r. but, in some cases add_out, shift_out, xnor_out, compare_outthe size is 4 bits only. so, during the case of these outputs, the output 'r' shows 4 X's.
module ALU(a,b,cin,sel,r,cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [7:0] r;
output cout;
wire [3:0] add_out, shift_out, xnor_out, compare_out;
wire [7:0] mul_out;
wire cout;
// MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
MUX6to2 output_mux (add_out, shift_out, xnor_out, mul_out, compare_out, sel[2:0], r);
Full_Adder_4bits output_adder (a,b,cin,sel [2:0],add_out,cout);
Shifter output_shifter (a,shift_out);
XNOR output_XNOR (a,b,xnor_out);
mul4 output_mul4 (a,b,mul_out);
Compare output_Compare (a,b,compare_out);
endmodule
Does your code compile properly? I can see a problem in this line:
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
Full_Adder_4bits, Shifter, etc. are names of your modules, not a valid signal names. What you meant is probably this:
Mux6to2 output_mux (adder_out, shifter_out, xnor_out, mul_out, compare_out, sel, r);
I'm a beginner at vhdl and I'm trying to make a 8 bit divider using shift and subtract method. The code for the divider is okay, I guess, but I'm having problems in simulating the inputs. When I use the Verilog test fixture, my inputs which should be (dividend=51 [00110011b], divisor=19 [00010011b]) always end up becoming (dividend=49 [00110001b], divisor=49 [00110001b])) in iSim, and then the outputs (Quotient and remainder = xxxxxxx (unknown)) instead of (quotient=2[00000010b] and remainder=13 [00001101b])...
As I mentioned before, I'm a beginner at vhdl and I've been at this for five hours, I've tried my best to search for a solution online, but failed.... so any help or alternative solution would be greatly appreciated.
I'm using Xilinx ISE 14.3 and iSim.
Here is the code for the 8 bit binary divider.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.STD_LOGIC_ARITH.all;
entity division is
generic(SIZE: INTEGER := 8);
port(reset: in STD_LOGIC; --reset
en: in STD_LOGIC; --enable
clk: in STD_LOGIC; --clock
num: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --dividend
den: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --divisor
res: out STD_LOGIC_VECTOR((SIZE - 1) downto 0); --result/quotient
rm: out STD_LOGIC_VECTOR((SIZE - 1) downto 0) --remainder
);
end division;
architecture behav of division is
signal bufreg: STD_LOGIC_VECTOR((2 * SIZE - 1) downto 0); --signal array to hold both accumulator and dividend registers as one i.e bufreg(18 bits)
signal dbuf: STD_LOGIC_VECTOR((SIZE - 1) downto 0); --signal array to hold the divisor
signal count: INTEGER range 0 to SIZE; --count to determine when to stop
alias ADreg is bufreg((2 * SIZE - 1) downto SIZE); --ADreg is is alias for top half of bufreg register(17th to 9th bit)
alias DVNDreg is bufreg((SIZE - 1) downto 0); --DVNDreg is is alias for bottom half of bufreg register(8th to 0th bit)
begin
--our process begins here
p_001: process(reset, en, clk)
begin
if reset = '1' then
res <= (others => '0');
rm <= (others => '0');
count <= 0;
elsif rising_edge(clk) then
if en = '1' then
case count is
when 0 =>
ADreg <= (others => '0');
DVNDreg <= num;
dbuf <= den;
res <= DVNDreg;
rm <= ADreg;
count <= count + 1;
when others =>
if bufreg((2 * SIZE - 2) downto (SIZE - 1)) >= dbuf then
ADreg <= '0' & (bufreg((2 * SIZE - 3) downto (SIZE - 1)) - dbuf((SIZE - 2) downto 0));
DVNDreg <= DVNDreg ((SIZE - 2) downto 0) & '1';
else
bufreg <= bufreg((2 * SIZE - 2) downto 0) & '0';
end if;
if count /= SIZE then
count <= count + 1;
else
count <= 0;
end if;
end case;
end if;
end if;
end process;
end behav;
And here is the code for the Verilog test fixture (.v file):
module BINdivisionTEST;
// Inputs
reg reset;
reg en;
reg clk;
reg [7:0] num ;
reg [7:0] den ;
// Outputs
wire [7:0] res;
wire [7:0] rm;
// Instantiate the Unit Under Test (UUT)
division uut (
.reset(reset),
.en(en),
.clk(clk),
.num(num),
.den(den),
.res(res),
.rm(rm)
);
initial begin
// Initialize Inputs
reset = 0;
en = 0;
clk = 0;
//num = 0;
//den = 0;
// Wait 100 ns for global reset to finish
#100;
en = 1;
#100;
clk=1;
num <= "00110011" ;
den <= "00010011" ;
// Add stimulus here
end
endmodule
My biggest problems seem to be initialization of the inputs and probably some mistaken assignments, misuse of the test fixture file and some bad coding.
I should also add that the divider code was compiled in vhdl, ISE 14.3.
I'm extremely sorry if this has been answered before and I don't mean to piss anyone off by uploading bad and amateur code. If this kind of problem has been addressed before could you please provide me with a link.
Again, any help is greatly appreciated.
The simulator may be treating those as strings instead of numbers. Try changing:
num <= "00110011" ;
den <= "00010011" ;
to:
num <= 8'b00110011;
den <= 8'b00010011;
I'm no expert on Verilog but it looks as if you might not be asserting Reset to your VHDL component before testing it.
That would lead "Count" in an uninitialised state so that when you use it, anything could happen and the "XXXX" outputs are a reflection of that.
The reset sequence should look like
En <= '0';
Clk <= '0';
Reset <= '1';
wait for 100 ns;
Reset <= '0';
wait for 100 ns;
-- start testing here
(in VHDL of course ... but it'll translate to Verilog easily)