Logic design final lab
Logic design final lab
ID: 2528487
FINAL LAB
Question 4.4: The control unit of this Datapath will be implemented by the FIBO_FSM. FIBO_FSM is
divided into two main subcomponents as FSM and FSM_DECO. The FSM will have four external
inputs START, ZERO_FLAG, CLK and RST and one output DONE to indicate that the calculation is
completed. This component performs all the required control operations providing three outputs as:
opcode, operand1 and operand2.
Figure 1 (state diagram for my control FSM)
My input is, “start” (ST). I saw no need to have a, ”reset” signal because a change in, the “start”
signal acts as my reset. I have nine states and as stated in the manual, the presence of a START
signal is enough to kick-start the calculation process. The two 2-bit integers (denoted by either 00,
01, 10, 11, and xx) correspond to registers (4 in total). The IZ corresponds to a variable I created
(IsZero) to check when the variable; count is zero. ST needs to be 1 until the second number is added
to the register, after that you don’t need a start signal. After we pass the set_num2 state, any
presence of the “start “signal will force us back to loading new numbers. I chose not to have a
“DONE” state and I considered that count2 will either head to an end state if it is satisfied or not, also
since the opcode of start state is 000, I theorized that since this corresponds to no operation, it could
signify and end
parameter size=4;
parameter
start=0,load_count=4'b0001,set_num1=4'b0010,set_num2=4'b0011,count1=4'b0100,R3toR1=4'b01
01;//start-S0,load_count-S1, set_num1-S2,set_num2-S3, count1-S4,R3toR1-S5
parameter R1pR2=4'b0110, R2toR3=4'b0111,countd=4'b1000,count2=4'b1001;//R1pR2-S6,R2toR3-
S7,countd-S8,count2-S9
input START,zero_flag,CLK,RST;
output reg[size-2:0]opcode;
reg[size-1:0]current_state,next_state;
output reg[size-3:0]operand1,operand2;
output reg DONE;
if(RST==1)
current_state<=start;
else
current_state<=next_state;
end
always@(current_state)
case(current_state)
start:begin
opcode=3'b000;
DONE=0;
end
load_count:begin
opcode=3'b100;
operand1=2'b00;
DONE=0;
end
set_num1:begin
opcode=3'b001;
operand1=2'b01;
DONE=0;
end
set_num2:begin
opcode=3'b001;
operand1=2'b10;
DONE=0;
end
count1:begin
opcode=3'b101;
operand1=2'b00;
DONE=0;
end
R3toR1:begin
opcode=3'b111;
operand1=2'b11;
operand2=2'b01;
DONE=0;
end
R1pR2:begin
opcode=3'b110;
operand1=2'b01;
operand2=2'b10;
DONE=0;
end
R2toR3:begin
opcode=3'b111;
operand1=2'b10;
operand2=2'b11;
DONE=0;
end
countd:begin
opcode=3'b011;
operand1=2'b00;
DONE=0;
end
count2:begin
opcode=3'b101;
DONE=1;
end
endcase
always@(current_state,zero_flag)
begin
next_state=start;
case(current_state)
start://start (SO)
if(START==0)
next_state=start;//holds
else
next_state=load_count;//moves to the next state
load_count://load_count(S1)
if(START==0)
next_state=load_count;//hold
else
next_state=set_num1;
set_num1://set_num1 (S2)
if(START==0)
next_state=set_num1;
else
next_state=set_num2;
set_num2://(S3)
if(START==0)
next_state=count1;
else
next_state=load_count;//goes back to await a new signal
count1://(S4)
if(START == 0)
begin
if(zero_flag==1)//first count check
begin
next_state=load_count;
end
else if(zero_flag==0)
begin
next_state=R3toR1;
end
end
R3toR1://(S5)
//R3toR1 state
if(START == 0)
next_state = R1pR2;
else
next_state = load_count;//to await new input
R1pR2://(S6)
//addition state
if(START == 0)
next_state = R2toR3;
else
next_state = load_count;
R2toR3://(S7)
//R2toR3 state
if(START == 0)
next_state = countd;
else
next_state = load_count;
countd://(S8)
//we subtract count by 1 in it's register
if(START == 0)
next_state = count2;
else
next_state = load_count;
count2://(S9)
//program end
if(START == 0)
begin
if(zero_flag==0)//final count check
begin
next_state=R3toR1;
end
else if(zero_flag==1)//final count check
begin
next_state=start;
end
else
next_state=load_count;
end
endcase
end
endmodule
I decided to use a 3-process mealy approach whereby I had 3 always blocks. My first always block is
dedicated to the next state logic, my second always block is dedicated to computing the output and
my final always block is dedicated to computing the next state. I was able to implement my state
diagram as a basis for designing the aforementioned Verilog code.
parameter size=4;
input[size-3:0] operand1,operand2;
input[size-2:0]opcode;
output [size-2:0]ALUOPCODE;
output reg[size-3:0] rd_addr1, rd_addr2,wrt_addr;
output reg wrt_en,load_data;
if(opcode==3'b001)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=0;
end
if(opcode==3'b010)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=0;
rd_addr1=operand1;
end
if(opcode==3'b011)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=0;
rd_addr1=operand1;
end
if(opcode==3'b100)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=1;
end
if(opcode==3'b101)
begin
wrt_en=0;
rd_addr1=operand1;
end
if(opcode==3'b110)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=0;
rd_addr1=operand1;
rd_addr2=operand2;
end
if(opcode==3'b111)
begin
wrt_addr=operand1;
wrt_en=1;
load_data=0;
rd_addr1=operand2;
end
end
endmodule
I designed the code to align with Table.2, provided in the manual. I also assigned opcode to
alu_opcode.
input CLK,START,RST,zeroflag;
output [size-3:0]wrt_addr,rd_addr1,rd_addr2;
output [size-2:0]alu_opcode;//alu_opcode
output load_data,wrt_en,DONE,clk;
wire[size-2:0]w1;//opcode
fsmlast a1(START,zeroflag,CLK,RST,DONE,w1,operand1,operand2);
fsmdeco
a2(w1,operand1,operand2,clk,alu_opcode,rd_addr1,rd_addr2,wrt_addr,wrt_en,load_data);
endmodule
For FIBO_FSM, I simply combined the two modules that are required, i.e. FSM (titled module,”
fsmlast” and FSM_DECO (titled, “fsmdeco”).
parameter size=4;
input START,CLK,RST;
input[size-1:0]count;
output DONE;
output[3:0]data;
fibofsm b1(w1,w2,w4,w5,w6,w11,w8,START,DONE,RST,CLK);
fbdatapath b2(w1,w2,w3,w4,w5,w6,w10,count,w8,data);
endmodule
In this module, I connected FIBO_FSM to the Datapath.
Final Testbench
module final_tb();
parameter size=4;
reg CLK,START,RST;
reg[size-1:0]count;
wire DONE;
wire[size-1:0]data;
integer i;
final DUT(START,DONE,CLK,count,data,RST);
initial
begin
CLK=1'b0;
end
always
begin
#25 CLK=~CLK;
end
initial
begin
START=0; RST=1; count=4'b0111;#300;
START=0; RST=1;#300;
START=1'b1; RST=0;#300;
for(i=0;i<20;i=i+1)
begin
count=count-4'b0001;
end
end
endmodule
I had challenges in changing the values of count, which we are supposed to get from data. To solve
that challenge, I initialized a value for count and I then used a for-loop to change the value of count. I
apologize for this crude method, but it gets the job partially done as you will witness in the
forthcoming simulation.
Final Simulation
I was able to rectify my aforementioned problem regarding count by initializing a value for count. The
start signal initiates the entire process. It should be one for the process to start until it takes in the
second value into the second register. After that, we don’t need it, an application of the start signal
will force the entire process to revert to loading new values. I attribute errors to mistakes in the
connections of the modules. I have an understanding of the purpose of the project and the concept of
Mealy FSMs and also Moore FSMs.