Single cycle MIPS processor instruction execution - mips

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.

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.

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

initial block delaying in verilog

When implementing a single cycle mips in Verilog. PC is initialized to address 0
then updates its value to PC+1 at the posedge of the clock which was also initialized to 0.
The problem is in simulation, the instruction at address 0 takes only half clock cycle then the PC increments by 4 and then the second instruction enters the processor.
simulation screenshot http://imagizer.imageshack.us/v2/800x600q90/36/0cxn.jpg
Neither initializing clock by 1 nor adding delays before initializing PC solved the problem
this is my clock module
`timescale 1ps / 1ps
module clk_gen( clk );
output reg clk ;
initial begin
clk<=0;
end
always begin
#1400 clk=!clk;
end
endmodule
PC module:
module PC(inPC, Address, clk);
input [31:0] inPC;
input clk;
output reg [31:0] Address;
initial begin
Address=32'd0;
end
always #( posedge clk) begin
Address <= inPC;
end
endmodule
The question does not seem to relate to your clock module but based on that code.
Assuming you are not expect this to be synthesisable. Idealy you defined a reg or logic value in one process.
NB if your simulator supports it I would define times with absolutes ie #1.4ns for your delay.
initial begin
clk <= 1'b0;
forever begin
#1.4ns clk <= ~clk ;
end
end

Sequential Division verilog

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

How to print a number in Assembly 8086?

I'm trying to write a function that receives a number (which I pushed earlier), and prints it. How can I do it?
What I have so far:
org 100h
push 10
call print_num
print_num:
push bp
mov bp, sp
mov ax, [bp+2*2]
mov bx, cs
mov es, bx
mov dx, string
mov di, dx
stosw
mov ah, 09h
int 21h
pop bp
ret
string:
What you're placing at the address of string is a numerical value, not the string representation of that value.
The value 12 and the string "12" are two separate things. Seen as a 16-bit hexadecimal value, 12 would be 0x000C while "12" would be 0x3231 (0x32 == '2', 0x31 == '1').
You need to convert the numerical value into its string representation and then print the resulting string.Rather than just pasting a finished solution I'll show a simple way of how this could be done in C, which should be enough for you to base an 8086 implementation on:
char string[8], *stringptr;
short num = 123;
string[7] = '$'; // DOS string terminator
// The string will be filled up backwards
stringptr = string + 6;
while (stringptr >= string) {
*stringptr = '0' + (num % 10); // '3' on the first iteration, '2' on the second, etc
num /= 10; // 123 => 12 => 1 => 0
if (num == 0) break;
stringptr--;
}