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 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)
I'm trying to write the test bench for my ALU but. I'm not sure if its written in a way that makes it work. For instance, should I use dut or uut? Have I initialized my inputs correctly? The output wave is just straight (doesn't change with each bit X's and one 0).
module Alu_test();
reg [7:0]pc;
reg [3:0] CCRin;
reg rst,clk;
reg [3:0] opcode;
reg[7:0] ra;
reg[7:0] rb;
reg [7:0] in_port;
reg[7:0] SP; //= 255
wire[7:0] SP_out;
wire [7:0] out_port;
wire[255:0] dmem;
wire[7:0] ra_out;
wire[7:0] rb_out;
wire [3:0] CCRo;
wire [7:0] npc;
ALU dut(opcode,ra,rb,ra_out,rb_out,rst,clk,pc,npc,CCRin,CCRo,SP,SP_out,in_port,out_port,dmem);
initial
begin
rst = 0;
clk = 0;
opcode = 0;
SP = 255;
CCRin = 0;
pc = 0;
in_port = 0;
ra = 0;
rb = 0;
#5
forever
#5 clk = ~clk;
#50
#5 opcode[3:0] = 4'b0000; //nop
#5 opcode[3:0] = 4'b0100; //add
ra =1;
rb =1;
#5 opcode[3:0] = 4'b0111; //shift left
ra =1;
rb =0;
#5 opcode[3:0] = 4'b1010; //push
ra =1;
rb =2;
end
endmodule
this is the module
module ALU(opcode,ra,rb,ra_out,rb_out,rst,clk,pc,npc,CCRin,CCRo,SP,SP_out,in_port,out_port,dmem);
wire [7:0] res; // result
input wire [7:0]pc;
output reg [7:0] npc;
input rst,clk;
input wire [3:0] opcode;
input wire[7:0] ra;
input wire[7:0] rb;
output reg[7:0] ra_out;
output reg[7:0] rb_out;
input wire[7:0] SP; // testbench haygebli SP el mafroud yeb2a = 255
output reg[7:0] SP_out;
input wire [7:0] in_port;
output reg [7:0] out_port;
output reg[255:0] dmem;
input wire [3:0] CCRin;
output reg [3:0] CCRo;
wire co;
wire cin;
wire [7:0] result; //total result
always #(posedge clk)
begin
SP_out = SP;
end
assign result = alu_out(ra,rb,cin);
assign res = result[1:0];
assign co = result[2];
function [8:0] alu_out;
input [1:0] ra,rb;
input cin;
case (opcode)
0: ;
4: assign alu_out = ra + rb;
5: assign alu_out = ra - rb;
6: assign alu_out = ~(ra & rb);
7: assign alu_out = {ra[7:0],cin};
8: assign alu_out = {ra[0],cin,ra[7:1]};
10: if (ra == 1)
begin
dmem[SP_out] = rb;
SP_out = SP_out-1;
end
else
begin
SP_out = SP_out +1;
rb_out = dmem[SP_out];
end
11: assign out_port = ra;
12: assign ra_out = in_port;
13: assign ra_out = rb;
default: begin
alu_out = 8'bxxxxxxxx;
end
endcase
endfunction
always#(posedge clk)
begin
if (res == 0)
CCRo[0] = 1;
else if ( res < 0)
CCRo[1] = 1;
else if (co == 1)
CCRo[2] = 1;
else if ( res < 0 & res > result)
CCRo[3] = 1;
else
CCRo = CCRin;
if (res)
ra_out = res;
npc = pc+1;
end
endmodule
Using dut as the instance name is fine. You can also use uut instead, if you prefer.
You should move the clock generation into its own initial block, then call $finish at the end of your original initial block. This should get you further. Now, 4 signals become known:
initial begin
rst = 0;
opcode = 0;
SP = 255;
CCRin = 0;
pc = 0;
in_port = 0;
ra = 0;
rb = 0;
#5;
#50;
#5 opcode[3:0] = 4'b0000; //nop
#5 opcode[3:0] = 4'b0100; //add
ra =1;
rb =1;
#5 opcode[3:0] = 4'b0111; //shift left
ra =1;
rb =0;
#5 opcode[3:0] = 4'b1010; //push
ra =1;
rb =2;
$finish;
end
initial begin
clk = 0;
forever #5 clk = ~clk;
end
Your dmem initializes to X. You need to drive in opcode=10 to set it to another value.