Sequential Division verilog - binary

Can anyone tell me what should be the width of dividend and divisor in sequential division. As of now i have designed the divider which has WIDTH_DIVID=2*wIDTH_DIVIS. If i voilate this relation my division fails. Can anyone help me with this
My verilog code as show below
// Description: module for serial Divider
// The dividend is loaded into the accumulator along with the guard bit.
// Then the 2's complement of the divisor is added to the upperpart of the
// accumulator along with the guard bit.Then the MSB of the accumulator is
// tested.
// 1. If it is cleared then 1 bit left shift of the accumulator is done and
// one is concantinated to the LSB of the accumulator.
// 2. If is is not cleared then the accumulator contents are shifted 1 bit
// left.
// After the division upper part of the accumulator contains the remainder
// and lower part contains the quotient.
//--------------------------------------------------------------------------
module division(//global inputs
i_clk,i_rst,
//outputs
o_quotient,o_remainder,o_done,o_overflow,
//input
i_dividend,i_divisor,i_start
);
//parameter declarations
parameter DIVIS_WIDTH =2; //width for divisor
parameter DIVID_WIDTH =2*DIVIS_WIDTH; //width for dividend,DIVID_WIDTH=2*DIVIS_WIDTH
localparam NPOWER = 6; //divisor width<=2**NPOWER
localparam NULL_VECTOR_S=32'h00000000;
localparam S0= 2'd0;
localparam S1= 2'd1;
localparam S2= 2'd2;
//global inputs
input i_clk;
input i_rst;
//outputs
output reg [DIVIS_WIDTH:0] o_quotient;
output reg [DIVIS_WIDTH-1:0] o_remainder;
output reg o_overflow;
output reg o_done;
//input
input [DIVID_WIDTH-1:0] i_dividend;
input [DIVIS_WIDTH-1:0] i_divisor;
input i_start; //indicates start of division
// reg and wire declarations
reg [DIVID_WIDTH:0] dividend_i; //Add extra guard bit
reg [DIVIS_WIDTH:0] divisor_i; //Add extra guard bit
reg [DIVIS_WIDTH-1:0] divisor_rect_i; //divisor used to check overflow
wire signquot_i; //Sign of quotient
wire signremain_i; //Sign of remainder
reg [DIVID_WIDTH+DIVIS_WIDTH-1:0] accumulator_i; // Shift register which holds both remainder and quotient
reg [DIVIS_WIDTH:0] aluout_i; //Used to add the upperpart of the shift register and the divisor
reg [NPOWER-1:0] count_i; //No.of iterations
reg pos_i;
reg neg_i;
reg [2:0] state;
reg [2:0] nextstate;
reg done_i;
//Sign product of quotient and remainder
assign signquot_i=((i_dividend[DIVID_WIDTH-1] ^ i_divisor[DIVIS_WIDTH-1]));
assign signremain_i=(i_dividend[DIVID_WIDTH-1]);
always#(posedge i_clk or posedge i_rst)
begin
if(i_rst==1)begin
dividend_i<=0;
divisor_i<=0;
divisor_rect_i<=0;
end else begin
divisor_rect_i<=i_divisor;
dividend_i<=({1'b0,i_dividend});
divisor_i<=(~({1'b0,i_divisor})+1);
end
end // else: !if(i_rst==1)
//Sequential Division
always#(posedge i_clk or posedge i_rst)
begin
if (i_rst==1)
accumulator_i <=0;
else begin
if(i_start==1)
accumulator_i<={dividend_i[DIVID_WIDTH-1:0],1'b0}; // Load Dividend in shift register
else if(pos_i==1)
accumulator_i<=({aluout_i[DIVIS_WIDTH-1:0],accumulator_i[DIVID_WIDTH-DIVIS_WIDTH-1:0],1'b1});//({newaccu_i[DIVID_WIDTH-1:0],1'b1});//shiting the new register value by one bit left and concantinatinf one at the LSB
else if(neg_i==1)
accumulator_i<=({accumulator_i[DIVID_WIDTH-1:0],1'b0});//Use the previous register value and shift 1 bit left
end
end // always# (posedge i_clk or posedge i_rst or posedge i_start)
//Adding the divisor to the upper part of the Shift register
always#(accumulator_i,divisor_i)
begin
aluout_i<=accumulator_i[DIVID_WIDTH : DIVID_WIDTH-DIVIS_WIDTH]+ divisor_i;
// newaccu_i<= ({aluout_i, accumulator_i[DIVID_WIDTH-DIVIS_WIDTH-1:0]});
end
//Control of states for division
always#(posedge i_clk or posedge i_rst)
begin
if (i_rst == 1) begin
state <= S0;
count_i <=0;
end else begin
state <= nextstate;
if (state==S1)
count_i <= count_i - 1;
else if (state==S0)
count_i <= (DIVIS_WIDTH);
end
end // always# (posedge i_clk or posedge i_rst)
//generating the control signals pos_i and neg_i to control division
always#(state,i_start,aluout_i,count_i)
begin
case (state)
S0 :begin
pos_i <= 0;
neg_i <= 0;
if (i_start==1)
nextstate <= S1;
else
nextstate <= S0;
end
S1 : begin
neg_i <= aluout_i[DIVIS_WIDTH];
pos_i <= ~(aluout_i[DIVIS_WIDTH]);
if (count_i==NULL_VECTOR_S[NPOWER_WIDTH-1])
nextstate <= S2; // Done
else
nextstate <= S1;// Next sub&shift
end
S2 : begin
pos_i <= 0;
neg_i <= 0;
nextstate <= S0;
end
default: begin
pos_i <= 0;
neg_i <= 0;
nextstate <= S0;
end
endcase // case (state)
end // always# (state,i_start,aluout_i,count_i)
//done signal to indicate end of division
always#(posedge i_clk or posedge i_rst)
begin
if(i_rst==1) begin
done_i<= 0;
end else begin
done_i <= (count_i==1)? 1'b1 : 1'b0;
end
end
//Assigning the outputs for unsigned division
always#(accumulator_i,done_i)
begin
o_done<=done_i;
o_remainder<=accumulator_i[DIVID_WIDTH:DIVID_WIDTH-DIVIS_WIDTH+1];
o_quotient<=(accumulator_i[DIVIS_WIDTH:0]);
o_overflow<=(((accumulator_i[DIVID_WIDTH:DIVID_WIDTH-DIVIS_WIDTH+1])>=divisor_rect_i))? 1'b1 : 1'b0;
end
endmodule // division

Just to be clear on the terms used:
a รท b = c, a is called the dividend or numerator, b the divisor or
denominator and the result c is called the quotient
Source Wikipedia.
The input width of the dividend (numerator) and divisor (denominator) will determine the size of the quotient. Adding lsbs (fractional bits) to the inputs will increase the quotient precision.
The final required widths should be the same as using the / operator. Try running this along side your code to help spot errors. For required width calculation I strongly suggest working through some examples on paper. Start by dividing 4 bit numbers and move up to larger numbers 5,6 bits to understand the pattern of bit growth.

Here is a parameterized serial divider in system verilog.
// returns max value ('1) if divide by zero or overflow occurs.
module unsigned_serial_divide #(
parameter N_WIDTH = 16 // Size of dividend
,parameter D_WIDTH = 16 // Size of divisor
,parameter Q_WIDTH = 16 // Size of quotient
,parameter F_WIDTH = 0 // Number of fractional bits in quotient.
)(
input wire clk
,input wire reset
,input wire go // hold high for continuous calculation or stobe high for single calculation
,input wire [N_WIDTH-1:0] dividend
,input wire [D_WIDTH-1:0] divisor
,output reg [Q_WIDTH-1:0] quotient // maintains last complete calculation.
//,output wire overflow // NOT IMPLEMENTED
,output wire done // stobes high if go is held high or indicated when single calculation complete
);
localparam COUNT_WIDTH = $clog2(Q_WIDTH);
localparam [COUNT_WIDTH-1:0] DIVIDE_COUNTS = (COUNT_WIDTH)'(Q_WIDTH - 1'b1);
localparam WN_WIDTH = N_WIDTH + F_WIDTH;
localparam WD_WIDTH = D_WIDTH + DIVIDE_COUNTS;
localparam CALC_WIDTH = ((WN_WIDTH > WD_WIDTH) ? WN_WIDTH : WD_WIDTH) + 1;
reg busy;
reg [COUNT_WIDTH-1:0] divide_count;
reg [WN_WIDTH-1:0] working_dividend;
reg [WD_WIDTH-1:0] working_divisor;
reg [Q_WIDTH-1:0] working_quotient;
initial begin
busy <= 0;
divide_count <= 0;
working_dividend <= 0;
working_divisor <= 0;
working_quotient <= 0;
quotient <= 0;
end
// Subtract with sign bit
wire [CALC_WIDTH-1:0] subtract_calc = {1'b0, working_dividend} - {1'b0, working_divisor};
// subtract_positive = (working_dividend > working_divisor);
wire subtract_positive = ~subtract_calc[CALC_WIDTH-1];
// if the next bit in quotient should be set then subtract working_divisor from working_dividend
wire [WN_WIDTH-1:0] dividend_next = (subtract_positive) ? subtract_calc[WN_WIDTH-1:0] : working_dividend;
wire [WD_WIDTH-1:0] divisor_next = working_divisor >> 1;
wire [Q_WIDTH-1:0] quotient_next = (working_quotient << 1) | (subtract_positive);
always #(posedge clk or posedge reset) begin
if (reset) begin
busy <= 0;
divide_count <= 0;
working_dividend <= 0;
working_divisor <= 0;
working_quotient <= 0;
quotient <= 0;
end else begin
if (go & ~busy) begin
busy <= 1;
divide_count <= DIVIDE_COUNTS;
working_dividend <= dividend << F_WIDTH; // scale the numerator up by the fractional bits
working_divisor <= divisor << DIVIDE_COUNTS; // align divisor to the quotient
working_quotient <= 0;
end else begin
if (divide_count == 0) begin
if (busy == 1) begin
quotient <= quotient_next;
end
busy <= 0;
end else begin
divide_count <= divide_count - 1'b1;
end
working_dividend <= dividend_next;
working_divisor <= divisor_next;
working_quotient <= quotient_next;
end
end
end
assign done = ~busy;
endmodule

Related

Verilog conditional assign outputs X where there should be 1

I am currently building a sign extender in Verilog based on the one present in the ARMv8 processor, but after the first result is extended, every subsequent result makes a 1 in the output into an X. How do I get rid of the X?
The module and the quick test bench I made are shown below.
Sign Extender:
`timescale 1ns / 1ps
module SignExtender(BusImm, ImmIns);
output [63:0] BusImm;
input [31:0] ImmIns;
wire extBit;
assign extBit = (ImmIns[31:26] == 6'bx00101) ? ImmIns[25]:
(ImmIns[31:24] == 8'bxxx10100) ? ImmIns[23]:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? ImmIns[20]:
1'b0;
assign BusImm = (ImmIns[31:26] == 6'bx00101) ? {{38{extBit}}, ImmIns[25:0]}:
(ImmIns[31:24] == 8'bxxx10100) ? {{45{extBit}}, ImmIns[23:5]}:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? {{55{extBit}}, ImmIns[20:12]}:
64'b0;
assign BusImm = 64'b0;
endmodule
Test Bench:
`timescale 1ns / 1ps
`define STRLEN 32
`define HalfClockPeriod 60
`define ClockPeriod `HalfClockPeriod * 2
module SignExtenderTest;
task passTest;
input [63:0] actualOut, expectedOut;
input [`STRLEN*8:0] testType;
inout [7:0] passed;
if(actualOut == expectedOut) begin $display ("%s passed", testType); passed = passed + 1; end
else $display ("%s failed: 0x%x should be 0x%x", testType, actualOut, expectedOut);
endtask
task allPassed;
input [7:0] passed;
input [7:0] numTests;
if(passed == numTests) $display ("All tests passed");
else $display("Some tests failed: %d of %d passed", passed, numTests);
endtask
reg [7:0] passed;
reg [31:0] in;
wire [63:0] out;
SignExtender uut (
.BusImm(out),
.ImmIns(in)
);
initial begin
passed = 0;
in = 32'hF84003E9;
#10;
begin
passTest(out, 63'b0, "Stuff", passed);
#10;
in = 32'hf84093ea;
#10;
passTest(out, 63'b0, "Stuff", passed);
end
end
endmodule
You seem to be treating x as a "don't-care" value in your comparisons, but it is not. x is a specific value which represents "unknown". Since you drive your input signals to all known values (0 or 1), all your == comparisons resolve to x, and your output has x in it. You should only compare bits you are interested in. For example, change:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? {{55{extBit}}, ImmIns[20:12]}:
to:
( (ImmIns[27:24] == 4'b1000) && (ImmIns[21] == 1'b0) ) ? {{55{extBit}}, ImmIns[20:12]}:
You need to make similar changes to all your comparisons.
Also, you drive BusImm with 2 continuous assignments. Get rid of this line:
assign BusImm = 64'b0;
These changes get the x out of your output.
Also consider using casez. Refer to IEEE Std 1800-2017, section 12.5.1 Case statement with do-not-cares.

summation series using octave of while loop

The summation
sun=0;
i=0;
while(i<=20)
while(j<=5)
y=i+2j
j=j+1;
end
j=0;
i=i+1
end
Failed with error
when I run it, it displays a lot of y=20+i
There are many problems with this code.
Here is a cleaned-up version below (i.e. appropriate indentation, spacing, etc) with comments
sun = 0; % What's the `sun` doing here? Did you mean `y`?
i = 0;
% Where's the initialisation of j in this list?
% You are using it below uninitialised!
while i <= 20 % Octave/matlab does not need brackets in `while`, `for`,
% `if` statements, etc.
while j <= 5 % Proper indentation clarifies scope of
% outer 'while' block
y = i + 2 * j % Octave/matlab do not support '2j' syntax.
% You need to multiply explicitly.
j = j + 1;
end
j = 0; % Why aren't you resetting this *before* the inner loop?
% How do you think your sum will be affected if `j` is,
% let's say `10`, at the start of this program?
i = i + 1 % Are you leaving the `;` out intentionally here?
% (and `y` above?). If you don't want these values
% printed on the console each time, put a `;` at the end.
end

Single cycle MIPS processor instruction execution

I am executing six instructions in this Single Cycle MIPS processor.
I am unable to figure error in ALU module.
Six instructions i am trying to execute are: Add, Sub, AND, OR, Load, Store
Right now, i am getting correct result for Addition only.
In five bit MUX, i have given an input 'a' and 'b'. How can i relate this input 'a' and 'b' to instruction source and detonation registers.
Also, how can i add 4 byte after the execution of each instruction (i.e. my program counter is unable to increment).
//ALU Block
module ALU (FunctField,ReadData1,out_inALU, ALUOp,ctr1,result);
input ALUOp;
input [5:0]FunctField;
input [31:0] ReadData1;
input [31:0] out_inALU;
output [2:0] ctr1;
reg [2:0] ctr1;
output [31:0] result;
reg [31:0] result;
always #(*)
begin
if(ALUOp == 1) //Arithmetic' Type Instructions
begin
case(FunctField)
//begin
6'b100000: ctr1 = 3'b010; //ADDITION in 'R' Type
6'b100010: ctr1 = 3'b110; // SUBTRACTION in 'R' Type
6'b100100: ctr1 = 3'b000; // AND in 'R' Type
6'b100101: ctr1 = 3'b001; // OR in 'R' Type
endcase
end
if(ALUOp == 0)
begin // LW/SW Type Instructions
if (ctr1 == 3'b010)
result = ReadData1 + out_inALU ;
else if (ctr1 == 3'b110)
result = ReadData1 - out_inALU ;
else if (ctr1 == 3'b000)
result = ReadData1 & out_inALU ;
else if (ctr1 == 3'b001)
result = ReadData1 | out_inALU;
end
result = ReadData1 | out_inALU ;
end
endmodule
// Data memory
module data_memory (ReadAddr, WriteAddr, WriteData1, clock,
MemWrite, MemRead,ReadData);
input [31:0] ReadAddr, WriteAddr, WriteData1;
input clock, MemWrite, MemRead;
reg [31:0] mem[0:50]; // For simulation this no. is enough
reg [31:0] i; // Temporary variable
output [31:0] ReadData;
reg [31:0] ReadData;
initial
begin
// Initial read-out
ReadData = 0;
// Initial memory content for testing purpose
for ( i = 0; i <= 50; i = i+1)
mem[i] = i;
end
// Memory content is always fetched with positive edge clock
always #(posedge clock)
begin
wait ( MemRead )
#10 ReadData = mem[ReadAddr];
wait ( MemWrite )
#10 mem[WriteAddr] = WriteData1;
end
endmodule
// Instruction Memory
module inst(addr,clock,instruction);
input clock;
input [ 31 : 0 ] addr;
output [ 31 : 0 ] instruction;
reg [ 31 : 0 ] instruction;
reg [ 31 : 0 ] MEM[0 :31 ] ;
initial
begin
MEM[ 0 ] <= 32'h10000011;
MEM[ 1 ] <= 32'h10000011 ;
MEM[ 2 ] <= 32'h20000022 ;
MEM[ 3 ] <= 32'h30000033 ;
MEM[ 4 ] <= 32'h40000044 ;
MEM[ 5 ] <= 32'h50000055 ;
MEM[ 6 ] <= 32'h60000066 ;
MEM[ 7 ] <= 32'h70000077 ;
MEM[ 8 ] <= 32'h80000088 ;
MEM[ 9 ] <= 32'h90000099 ;
end
always #( posedge clock )
begin
instruction <= MEM[ addr ] ;
end
endmodule
//Main module
module(reset, clock, regwrite,regDst,ALUSrc,MemtoReg,MemWrite,MemRead, input_PC)
input reset,clock;
input regWrite;
input regDst;
input ALUSrc;
input MemtoReg;
input MemWrite;
input MemRead;
input [31:0] input_PC;
wire [4:0] ReadReg1, ReadReg2, WriteReg;
wire [31:0] WriteData;
// Instantiation of modules
//Program Counter
wire [31:0] addr;
PC x1(input_PC,clock,reset,addr);
// Instruction Memory
wire [31:0] instruction;
inst x2(addr,clock,instruction);
//Multiplexer with regDst
reg[4:0] inputa,inputb;
MUX_2to1_5bit x3(inputa,inputb,regDst,WriteReg);
//Register File
wire [31:0] ReadData1,ReadData2;
Register_32 x4 ( ReadReg1, ReadReg2, WriteReg, WriteData, clock,
RegWrite,ReadData1, ReadData2);
//Sign Extender
wire [31:0] out_sign;
SignExtender_16to32 x5(immediate, out_sign);
//Multilpexer ALUSrc
wire [31:0] out_inALU;
MUX_2to1 x6( ReadData2 , out_sign, ALUSrc,out_inALU );
//ALU
wire [31:0] result;
wire [2:0] ctr1;
ALU x7 (FunctField,ReadData1,out_inALU, ALUOp,ctr1,result);
//Data Memory
reg [31:0] ReadAddr;
reg [31:0] WriteAddr;
wire [31:0] ReadData;
data_memory x8(ReadAddr, WriteAddr, WriteData, clock, MemWrite,
MemRead,ReadData);
//Multiplexer MemtoReg
MUX_2to1_memreg x9( result,ReadData,MemtoReg,WriteData);
endmodule
// Mux2 to 1_32 bit
module MUX_2to1( ReadData2 , outputData, ALUSrc,out_inALU );
input [31:0] ReadData2,outputData;
input ALUSrc;
output [31:0]out_inALU;
reg [31:0]out_inALU;
always #(ReadData2 or outputData or ALUSrc )
begin
case(ALUSrc)
1'b0: out_inALU=ReadData2;
1'b1: out_inALU=outputData;
endcase
end
endmodule
// Mux 2 to 1 5 bit
module MUX_2to1_5bit( inputa , inputb, regDst, WriteReg);
input [4:0] inputa, inputb;
input regDst;
output [4:0]WriteReg;
reg [4:0]WriteReg;
always #(inputa or inputb or regDst )
begin
case(regDst)
1'b0: WriteReg=inputa;
1'b1: WriteReg=inputb;
endcase
end
endmodule
// Mux 2 to 1 for memory register
module MUX_2to1_memreg( result,ReadData,MemtoReg,WriteData);
input [31:0] ReadData,result;
input MemtoReg;
output [31:0] WriteData;
reg [31:0]WriteData;
always #(* )
begin
case(MemtoReg)
1'b0: WriteData= result ;
1'b1: WriteData= ReadData;
endcase
end
endmodule
// Progrma COunter
module PC(input_PC,clock,reset,addr);
input reset,clock;
input [31:0] input_PC;
output reg [31:0] addr;
always #(posedge clock)
begin
if (reset)
addr=0;
else
addr=input_PC+4;
end
endmodule
//Register
module Register_32 ( ReadReg1, ReadReg2, WriteReg,
WriteData, clock, RegWrite,ReadData1, ReadData2);
input [4:0] ReadReg1, ReadReg2, WriteReg;
input [31:0] WriteData;
input clock, RegWrite;
output [31:0] ReadData1, ReadData2;
reg [31:0] ReadData1, ReadData2;
reg [31:0] mem[0:31]; // 32 32-bit registers
reg [5:0] i; // Temporary variable
initial
begin
// Initial registers for testing purpose
for ( i = 0; i <= 31; i = i+1)
mem[i] = i;
// Initial start-up
ReadData1 = 0;
ReadData2 = 0;
end
// Data from register is always fetched with positive edge clock
always #(posedge clock)
begin
#1 ReadData1 = mem[ReadReg1];
#1 ReadData2 = mem[ReadReg2];
if ( RegWrite == 1)
#1 mem[WriteReg] = WriteData;
end
endmodule
// Sign extender
module SignExtender_16to32(immediate,out_sign);
input[15:0] immediate;
output[31:0] out_sign;
reg [31:0] out_sign;
always#(*)
begin
out_sign[15:0] = immediate[15:0];
out_sign[31:16] = {16{immediate[15]}};
end
endmodule
You could increment the program counter as below but it will have wrap around issues. Better to have a signal to latch the input address or at reset do add = input_PC;
module PC(input_PC,clock,reset,addr);
input reset,clock;
input [31:0] input_PC;
output reg [31:0] addr;
always #(posedge clock)
begin
if (reset)
addr= 0;
else
addr=input_PC+4+addr;
end
endmodule
you would want the mem to ignore lower 2 bits in inst module else after reading mem 0 it will read mem[4] .
instruction <= MEM[ addr[31:2] ] ;
You need to connect the instruction to the ALU module , cannot offer any suggestion as i cannot figure what your instruction decoding scheme is.

FPGA output pins outputting wrong state

I am writing a LCD controller for an FPGA and am having a really weird (for me at least) problem. The state machine that's supposed to output the needed bits to the screen misbehaves and gets the output pins "stuck" in an old state, while it clearly has moved on to later states.
Here is the relevant parts of the state machine:
PROCESS (clk)
VARIABLE count: INTEGER RANGE 0 TO clk_divider; -- clk_divider is a generic positive.
BEGIN
IF (clk'EVENT AND clk = '1') THEN
count := count + 1;
IF (count = clk_divider) THEN
EAUX <= NOT EAUX;
count := 0;
END IF;
END IF;
END PROCESS;
....
PROCESS (EAUX)
BEGIN
IF (EAUX'EVENT AND EAUX = '1') THEN
pr_state <= nx_state;
END IF;
END PROCESS;
....
PROCESS (pr_state)
BEGIN
CASE pr_state IS
WHEN EntryMode => --6=1,7=Cursor increment/decrement, 8=Display shift on/off
RSs <='0';
DB(7 DOWNTO 0) := "00000110";
nx_state <= WriteData;
WHEN WriteData => --Write data to LCD:
RSs <='1';
YLED <= '1';
DB(7 DOWNTO 0) := "01011111";
i := i + 1;
IF (i < chars) THEN
nx_state <= WriteData;
ELSE
i := 0;
nx_state <= ReturnHome;
END IF;
WHEN ReturnHome => --Return cursor
RSs <='0';
YLED <= '1';
DB(7 DOWNTO 0) := "01011111";
nx_state <= WriteData;
END CASE;
END PROCESS;
Where the bits in the variable DB is assigned to the signal DBOUT:
DBOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- In entity
SHARED VARIABLE DB : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; -- In Architecture
DBOUT <= DB;
DBOUT is outputted (in the .ucf-file) as:
NET "DBOUT(0)" LOC = P10;
NET "DBOUT(1)" LOC = P11;
NET "DBOUT(2)" LOC = P12;
NET "DBOUT(3)" LOC = P13;
NET "DBOUT(4)" LOC = P15;
NET "DBOUT(5)" LOC = P16;
NET "DBOUT(6)" LOC = P18;
NET "DBOUT(7)" LOC = P19;
Using an oscilloscope on the pins I can see that it is clearly stuck outputting the "EntryMode" bits and the "RSs" is set at low, while the YLED (the internal led on the FPGA) is on (it's off at all other states). The really weird thing is (and this took a real long time to find) is that if I change the EntryMode bits from
"00000110"
to
"00000100"
it successfully passes the state and outputs the correct bits. It might be true for other changes as well, but I don't really feel like testing that too much. Any help or tips would be highly appreciated!
UPDATE:
After popular request I explicitly put YLED to low in all the early states and switched (back) DB to be a signal. The result is that I can't reach the later states at all, or at least stay in them (even when fiddling with the magic bits, which I guess is a good thing) as the YLED only stays on for a split second after booting the FPGA.
There is a complete example, including theory, state machine, and VHDL code on pages 279-290 of "Finite State Machines in Hardware: Theory and Design...", by Volnei Pedroni, MIT Press, Dec. 2013.

FFT implemetation in Verilog: Assigning Wire input to Register type array

I am trying to implement butterfly FFT algorithm in verilog.
I create K(Here 4) butterfly modules . I create modules like this.
localparam K = 4;
genvar i;
generate
for(i=0;i<N/2;i=i+1)
begin:BN
butterfly #(
.M_WDTH (3 + 2*1),
.X_WDTH (4)
)
bf (
.clk(clk),
.rst_n(rst_n),
.m_in(min),
.w(w[i]),
.xa(IN[i]),
.xb(IN[i+2]),
.x_nd(x_ndd),
.m_out(mout[i]),
.ya(OUT[i]),
.yb(OUT[i+2]),
.y_nd(y_nddd[i])
);
end
Each level I have to change input Xa and Xb for each Module (Here Number of level 3).
So I try to initialize reg type "IN"array and assign the array to input Xa and Xb. When I initialize "IN" array manually, it works perfectly.
The problem I face now, I couldn't assign Main module input X to register type "IN" array.
Main module input X ,
input wire signed [N*2*X_WDTH-1:0] X,
I have to assign this X into array "IN",
reg signed [2*X_WDTH-1:0] IN [0:N-1];
I assigned like this,
initial
begin
IN[0]= X[2*X_WDTH-1:0];
IN[1]=X[4*X_WDTH-1:2*X_WDTH];
IN[2]=X[6*X_WDTH-1:4*X_WDTH];
IN[3]= X[8*X_WDTH-1:6*X_WDTH];
IN[4]= X[10*X_WDTH-1:8*X_WDTH];
IN[5]=X[12*X_WDTH-1:10*X_WDTH];
IN[6]=X[14*X_WDTH-12*X_WDTH];
IN[7]= X[16*X_WDTH-1:14*X_WDTH];
end
I have gone through many tutorials and forums. No luck.
Can't we assign wire type to reg type array? If so how I can solve this problem.
Here is the Main module where I initialize Butterfly modules,
module Network
#(
// N
parameter N = 8,
// K.
parameter K = 3,
parameter M_WDTH=5,
parameter X_WDTH=4
)
(
input wire clk,
input wire rst_n,
// X
input wire signed [N*2*X_WDTH-1:0] X,
//Y
output wire signed [N*2*X_WDTH-1:0] Y,
output wire signed [K-1:0] y_ndd
);
wire y_nddd [K-1:0];
assign y_ndd ={y_nddd[1],y_nddd[0]};
reg [4:0] min=5'sb11111;
wire [4:0] mout [0:K-1];
reg x_ndd;
reg [2:0] count=3'b100;
reg [2*X_WDTH-1:0] w [K-1:0];
reg [2*X_WDTH-1:0] IN [0:N-1];
wire [2*X_WDTH-1:0] OUT [0:N-1];
assign Y = {OUT[3],OUT[2],OUT[1],OUT[0]};
reg [3:0] a;
initial
begin
//TODO : Here is the problem. Assigning Wire to reg array. Synthesize ok. In Simulate "red" output.
IN[0]= X[2*X_WDTH-1:0];
IN[1]=X[4*X_WDTH-1:2*X_WDTH];
IN[2]=X[6*X_WDTH-1:4*X_WDTH];
IN[3]= X[8*X_WDTH-1:6*X_WDTH];
IN[4]= X[10*X_WDTH-1:8*X_WDTH];
IN[5]=X[12*X_WDTH-1:10*X_WDTH];
IN[6]=X[14*X_WDTH-12*X_WDTH];
IN[7]= X[16*X_WDTH-1:14*X_WDTH];
//TODO :This is only a random values
w[0]=8'sb01000100;
w[1]=8'sb01000100;
w[2]=8'sb01000100;
w[3]=8'sb01000100;
end
/* levels */
genvar i;
generate
for(i=0;i<N/2;i=i+1)
begin:BN
butterfly #(
.M_WDTH (3 + 2*1),
.X_WDTH (4)
)
bf (
.clk(clk),
.rst_n(rst_n),
.m_in(min),
.w(w[i]),
.xa(IN[i]),
.xb(IN[i+N/2]),
.x_nd(x_ndd),
.m_out(mout[i]),
.ya(OUT[2*i]),
.yb(OUT[2*i+1]),
.y_nd(y_nddd[i])
);
end
endgenerate
always # (posedge clk)
begin
if (count==3'b100)
begin
count=3'b001;
x_ndd=1;
end
else
begin
count=count+1;
x_ndd=0;
end
end
always# (posedge y_ndd[0])
begin
//TODO
//Here I have to swap OUT-->IN
end
endmodule
Any help is appreciated.
Thanks in advance.
"Output is red", this likely means it is x this could be due to multiple drivers or an uninitialized value. If it was un-driven it would be z.
The main Issue I believe is that you do this :
initial begin
IN[0] = X[2*X_WDTH-1:0];
IN[1] = X[4*X_WDTH-1:2*X_WDTH];
...
The important part is the initial This is only evaluated once, at time 0. Generally everything is x at time zero. To make this an equivalent of the assign IN[0] = ... for a wire use always #* begin this is a combinatorial block which will update the values for IN when ever X changes.
always #* begin
IN[0] = X[2*X_WDTH-1:0];
IN[1] = X[4*X_WDTH-1:2*X_WDTH];
...
I am not sure why you do not just connect your X to your butterfly .xa and .xb ports directly though?
Other pointers
X is a bad variable name verilog as a wire or reg can hold four values 1,0,x or z.
In always #(posedge clk) you should be using non-blocking (<=) assignments to correctly model the behaviour of a flip-flop.
y_ndd is k bits wide but only the first 2 bits are assigned.
output signed [K-1:0] y_ndd
assign y_ndd = {y_nddd[1],y_nddd[0]};
Assignments should be in terms of their parameter width/size. For example IN has N entries but currently exactly 8 entries are assigned. There will been an issue when N!=8. Look into Indexing vectors and arrays with +:. Example:
integer idx;
always #* begin
for (idx=0; idx<N; idx=idx+1)
IN[idx] = X[ idx*2*X_WDTH +: 2*X_WDTH];
end
genvar gidx;
generate
for(gidx=0; gidx<N; gidx=gidx+1) begin
assign Y[ gidx*2*X_WDTH +: 2*X_WDTH] = OUT[gidx];
end
endgenerate