Lab 6 Finite State Machines Solution

$35.00

Description

  • Learning Objectives

The purpose of this lab is to learn how to create FSMs as well as use them to control a datapath over multiple clock cycles.

  • Marking Scheme

This lab worth 4% of your nal grade, but you will be graded out of 8 marks for this lab, as follows:

  • Prelab – Simulations: 3 marks

  • Part I (in-lab): 2 marks

  • Part II (in-lab): 3 marks

  • Part III (bonus): 2 marks (1 for prelab, 1 for in-lab demo)

  • Preparation Before the Lab

You are required to complete Parts I and II of the lab by writing and testing Verilog code with Modelsim (using reasonable test vectors that you can justify). Part III is optional, but has a prelab component, should you choose to do it. You should hand-in your prelab preparations (schematics, Verilog, and simulation outputs) for Parts I to II to the TAs (and Part III, if you choose to do it).

In-lab Work

You are required to implement and test all of Parts I and II of the lab (and Part III, if you choose to do it). You should demonstrate them to the teaching assistants when you nished testing them.

  • Part I

We aim to implement a nite state machine (FSM) that recognizes two speci c sequences of applied input symbols: four consecutive 1s or the sequence 1101. There is an input w and an output z. Whenever w = 1 for four consecutive clock pulses, or when the sequence 1101 appears on w across four consecutive clock pulses, the value of z has to be 1; otherwise, z = 0. Overlapping sequences are allowed, so that if w = 1 for ve consecutive clock pulses the output z will be equal to 1 after the fourth and fth pulses. Figure 1 illustrates the required relationship between w and z. A state diagram for this FSM is shown in Figure 2.

Figure 3 shows a starter Verilog code for the required state machine. Study and understand this code as it provides a model for how to clearly describe a nite state machine that will both simulate and synthesize properly. It has missing parts that you should complete yourself.

1

!”#$%&

‘&

(&

Figure 1: Required timing for the output z.

,-.-/$

01#$

!”#$

01)$

01#$

%”#$

01)$

01#$

01#$

&”#$

01)$

01#$

01)$

01#$

‘”

01#$

*”#$

#$

01)$ 01)$

+”

(“)$ )$

01)$

Figure 2: A state diagram for the FSM.

2

// SW[0]:

r e s e t

s i g n a l

// SW[1]:

i n p u t

s i g n a l

(w)

// KEY[0]:

c l o c k

// LEDR[2:0]:

c u r r e n t

s t a t e

// LEDR[ 9 ] :

o u t p u t

( z )

module s e q u e n c e

d e t e c t o r (SW, KEY,

LEDR) ;

input

[9:0]

SW;

input

[3:0]

KEY;

output

[9:0]

LEDR;

wire w,

c l o c k ,

r e s e t n ,

z ;

reg

[2:0]

y Q ,

Y D ;

//

y Q

r e p r e s e n t s

c u r r e n t

s t a t e ,

Y D r e p r e s e n t s n e x t s t a t e

localparam A =

3 ’ b000 ,

B =

3 ’ b001 , C =

3 ’ b010 ,

D = 3 ’ b011 , E =

3 ’ b100 , F = 3 ’ b101 , G = 3 ’ b110 ;

//

Connect

i n p u t s

and

o u t p u t s

t o i n t e r n a l

w i r e s

assign w = SW[ 1 ] ;

assign

c l o c k

=

~KEY[ 0 ] ;

assign

r e s e t n = SW[ 0 ] ;

assign LEDR [ 9 ]

=

z ;

assign LEDR [ 2 : 0 ]

= y Q ;

// S t a t e t a b l e

//

The

s t a t e

t a b l e

s h o u l d

o n l y

c o n t a i n

t h e

l o g i c f o r

s t a t e t r a n s i t i o n s

// Do not mix i n any

o u t p u t

l o g i c .

The o u t p u t

l o g i c

s h o u l d be

h a n d l e d s e p a r a t e l y .

//

This

w i l l

make

i t

e a s i e r

t o

read ,

modify and debug

t h e code .

always @( )

begin

//

S t a r t

o f

s t a t e

t a b l e

case

( y Q )

A: begin

i f

( ! w)

YD=A;

else

YD=B;

end

B :

begin

i f ( ! w)

YD=A;

else

YD=C;

end

C:

. . .

//

To be c o m p l e t e d by you !

D:

. . .

//

To be c o m p l e t e d by you !

E :

. . .

//

To be c o m p l e t e d by you !

F :

. . .

//

To be c o m p l e t e d by you !

G:

. . .

//

To be c o m p l e t e d by you !

default : Y D = A;

endcase

end

//

End

o f

s t a t e t a b l e

// S t a t e

R e g i s t e r

( i . e . , FFs )

always @( posedge

c l o c k )

begin

//

S t a r t

o f

s t a t e

F F s

( s t a t e

r e g i s t e r )

i f ( r e s e t n == 1 ’ b0 )

y Q <= A;

else

y Q <= Y D ;

end

//

End

o f

s t a t e F F s

( s t a t e r e g i s t e r )

//

Output

l o g i c

//

S e t

z

t o

1

t o

t u r n

on LED when i n

r e l e v a n t

s t a t e s

assign

z

=

( ( y Q ==

???)

j j

( y Q ==

???));

//

To be

c o m p l e t e d

by you !

endmodule

Figure 3: Starter Verilog code for the FSM (sequence detector.v)

3

The toggle switch SW 0 on the DE1-SoC board is the reset signal input for the FSM, SW 1 is the w input, and the pushbutton KEY 0 is the clock input that is applied manually. The LED LEDR9 shows the output z, and the state of system is shown on LEDR2 0.

For this part, you should follow the following steps:

  1. Begin with the starter code sequence_detector.v (Figure 3) that we provided to you (on the Blackboard, as well as in the appendices of this handout).

  1. Answer the following questions in your prelab: given the starter code, is the resetn signal is an synchronous or asynchronous reset? Is it active high, or active low? Given this, what do you have to do in simulation to reset the FSM to the starting state? (PRELAB)

  1. Complete the state table showing how the present state and input value determine the next state and the output value. Fill in all the missing parts of the template code to implement the FSM based on the state table you derived. Include completed code in your prelab. (PRELAB)

  1. Simulate your circuit using ModelSim for a variety of input settings, ensuring the output waveforms are correct. Include a few screenshots that shows the simulation output. (PRELAB)

  1. Create a new Quartus Prime project for your circuit. Make sure to store it in your W:\ drive; select the correct FPGA device (5CSEMA5F31C6); and import the pin assignments. Compile the project. (IN-LAB)

  1. Download the compiled circuit into the FPGA. Test the functionality of the circuit on your board. When you are sure that it is working correctly, show it to TAs. (IN-LAB)

  • Part II

Most non-trivial digital circuits can be separated into two main functions. One is the datapath where the data ows and the other is the control path that manipulates the signals in the datapath to control the operations performed and how the data ows through the datapath. In previous labs, you learned how to construct a simple ALU, which is a common datapath component. In Part I of this lab you constructed a simple nite state machine (FSM), which is the most common component used to implement a control path. Now you will see how to implement an FSM to control a datapath so to perform a useful operation. This is an important step towards building a microprocessor as well as any other computing circuit.

In this part, you are given a datapath and a FSM that controls it to compute A2 + C. Using the given datapath, you should implement a di erent FSM that controls the datapath to perform the following computation:

Ax2 + Bx + C

The values of x, A, B and C will be preloaded by the user on the switches before the computation begins.

Figure 4 shows the block diagram of the datapath you will build. There are a few things to note about this diagram:

  • Reset signals are not shown to reduce clutter, but do not forget to include them when writing your Verilog code.

  • The datapath will operate on 8-bit unsigned values. Assume that the input values are small enough

to not cause any over ows at any point in the computation, i.e., no results will exceed 28 1 = 255.

  • The ALU needs to perform only addition and multiplication, but you could use a variation of the ALU you built previously to have more operations available for solving other equations if you wish to try some things on your own.

  • There are four registers Rx, RA, RB and RC used at the start to store the values of x, A, B and C, respectively. The registers RA and RB can be overwritten during the computation.

4

  • There is one output register, RR, that captures the output of the ALU and displays the value in binary on the LEDs and in hexadecimal on the HEX displays.

  • Two 8-bit-wide, 4-to-1 multiplexers at the inputs to the ALU are used to select which register values are input to the ALU.

  • All registers have enable signals to determine when they are to load new values and an active low synchronous reset.

data_in

ld_alu_out

ld_c

ld_x

ld_a

ld_b

C

X

A

B

alu_select_a

alu_select_b

alu_op

ld_r

R

data_result

Figure 4: Block diagram of datapath.

The provided circuit should operate in the following manner:

After an active low synchronous reset on KEY 0, you will input the value for RA on switches SW[7 : 0].

  • When KEY 1 is pushed and released, RA will be loaded. Then you will input the next value on the switches that will be loaded into RB, and press and release KEY 1. You repeat this to load RC and RX .

  • Computation will start after KEY 1 is pressed and released for loading RX .

  • When computation is nished, the nal result will be loaded into RR.

  • This nal result should be displayed on LEDR7 0 in binary and HEX0 and HEX1 in hex.

Note that KEY 1 is NOT your clock! You will use the 50 MHz clock available through input CLOCK 50 as your clock.

Perform the following steps for this part:

  1. Examine the provided starter Verilog code for this part (poly_function.v, which is available on the Blackboard, as well as in the appendices of this handout). This is a major step in this part of the lab. You will not need to write much Verilog yourself, but you will need to fully understand the circuitry described by the provided Verilog to be able to make your modi cations. (PRELAB)

  1. Determine a sequence of steps similar to the datapath example shown in lecture that controls your datapath to perform the required computation. You should draw a table that shows the state of the Registers and control signals for each cycle of your computation. Include this table in your prelab. (PRELAB)

5

  1. Draw a state diagram for your controller starting with the register load states provided in the example FSM. Include the state diagram in your prelab. (PRELAB)

  1. Modify the provided FSM code to implement your controller and synthesize it. You should only modify the control module. Inlclude your modi ed code in the prelab. (PRELAB)

  1. To examine the circuit produced by Quartus Prime open the RTL Viewer tool (Tools > Netlist Viewers > RTL Viewer). Find (on the left panel) and double-click on the box shown in the circuit that represents the nite state machine, and determine whether the state diagram that it shows properly corresponds to the one you have drawn. To see the state codes used for your FSM, open the Compilation Report, select the Analysis and Synthesis section of the report, and click on State Machines. Include a screenshot of the generated FSM in your prelab. (PRELAB)

The state codes after synthesis may be di erent from what you originally speci ed. This is because the tool may have found a way to optimize the logic better by choosing a di erent state assignment. If you really need to use your original state assignment, there is a setting to keep it (which we do not investigate here).

  1. Simulate your circuit with ModelSim for a variety of input settings, ensuring the output waveforms are correct. It is recommended that you start by simulating the datapath and controller modules separately. Only when you are satis ed that they are working individually should you combine them into the full design. Why is this approach better? (Hint: Consider the case when your design has 20 di erent modules.) Include few screenshots of simulation output in your prelab. (PRELAB)

  1. Compile your project in Quartus, program the FPGA in DE1 board, and test it with various inputs. After you are satis ed that your circuit is working properly, show it to TAs. (IN-LAB)the functionality of the circuit on the FPGA board.

  • Part III (Optional)

Note: Only start working on this part if you already completed other parts. This is an optional part that provides a more challenging exercise for you to further test your knowledge.

Addition, subtraction and multiplication are much easier to build in hardware than division. So division is the most complex operation in hardware. For this part, you will design a 4-bit restoring divider using a nite state machine.

Figure 5 shows an example of how the restoring divider works. This mimics what you do when you do long division by hand. In this speci c example, number 7 (Dividend) is divided by number 3 (Divisor). The restoring divider starts with Register A set to 0. The Dividend is shifted left and the bit shifted out of the left most bit of the Dividend (called the most signi cant bit or MSB) is shifted into the least signi cant bit (LSB) of Register A as shown in Figure 6.

The Divisor is then subtracted from Register A. This is equivalent to adding the 2’s complement of the Divisor (11101 for the example in Figure 5) to Register A. If the MSB of Register A is a 1, then we restore Register A back to its original value by adding the Divisor back to Register A, and set the LSB of the Dividend to 0. Else, we do not perform the restoring addition and immediately set the LSB of the Dividend to 1.

This cycle is performed until all the bits of the Dividend have been shifted out. Once the process is complete, the new value of the Dividend register is the Quotient, and Register A will hold the value of the Remainder.

To implement this part, you will use SW 3

0 for the divisor value and SW 7 4 for the dividend value.

Use CLOCK

50 as the clock signal, KEY 0

as a synchronous active high reset, and KEY 1 as the Go

signal to start computation. The output of the Divisor will be displayed on HEX0, the Dividend will

6

Figure 5: An example of how a restoring divider works.

Figure 6: Block diagram of restoring divider.

7

be displayed on HEX2, the Quotient on HEX4, and the Remainder on HEX5. Set the remaining HEX displays to 0. Also display the Quotient on LEDR.

Structure your code in the same way as you were shown in Part II and follow these steps for this part:

  1. Draw a schematic for the datapath of your circuit. It will be similar to Figure 6. You should show how you will initialize the registers, where the outputs are connected to, and include all the control signals that you require.

  1. Draw the state diagram that controls your datapath.

  1. Draw the schematic for your controller module.

  1. Draw the top-level schematic showing how the datapath and controller are connected as well as the inputs and outputs to your top-level circuit.

  1. Write the Verilog code that implements your circuit.

  1. Simulate your circuit in ModelSim for a variety of input settings.

  1. After you are satis ed with your simulations, download and test it on the FPGA board.

8

Appendices: Source Codes

  • sequence detector.v

// SW[0]:

r e s e t

s i g n a l

// SW[1]:

i n p u t

s i g n a l

(w)

// KEY[0]:

c l o c k

// LEDR[2:0]:

c u r r e n t

s t a t e

// LEDR[ 9 ] :

o u t p u t

( z )

module s e q u e n c e

d e t e c t o r (SW,

KEY,

LEDR) ;

input

[9:0]

SW;

input

[3:0]

KEY;

output

[9:0]

LEDR;

wire w,

c l o c k ,

r e s e t n ,

z ;

reg [ 2 : 0 ] y Q ,

Y D ;

//

y

Q

r e p r e s e n t s

c u r r e n t

s t a t e ,

Y

D r e p r e s e n t s n e x t s t a t e

localparam A =

3 ’ b000 ,

B =

3 ’ b001 , C =

3 ’ b010 ,

D = 3 ’ b011 , E =

3 ’ b100 ,

F = 3 ’ b101 , G

// Connect i n p u t s

and

o u t p u t s

t o i n t e r n a l w i r e s

assign w = SW[ 1 ] ;

assign

c l o c k

= ~KEY[0];

assign

r e s e t n = SW[ 0 ] ;

assign LEDR [ 9 ]

=

z ;

assign LEDR [ 2 : 0 ] = y Q ;

// S t a t e t a b l e

// The

s t a t e

t a b l e

s h o u l d

o n l y

c o n t a i n

t h e l o g i c

f o r

s t a t e t r a n s i t i o n s

// Do not mix i n

any o u t p u t

l o g i c .

The o u t p u t

l o g i c

s h o u l d be

h a n d l e d

s e p a r a t e l y .

// This

w i l l

make

i t e a s i e r

t o

read ,

modify and

debug

t h e code .

always @( )

begin

// S t a r t

o f

s t a t e

t a b l e

case ( y Q )

  1. begin

i f ( ! w) Y D = A; else Y D = B ;

end

B : begin

i f ( ! w) Y D = A;

else Y D = C;

end

  1. . . . // To be c o m p l e t e d by you !

D: …

//

To

be

c o m p l e t e d

by

you !

E: …

//

To

be

c o m p l e t e d

by

you !

F: …

//

To

be

c o m p l e t e d

by

you !

  1. . . . // To be c o m p l e t e d by you ! default : Y D = A;

endcase

end

// End o f

s t a t e

t a b l e

//

S t a t e R e g i s t e r

( i . e . , FFs )

always @( posedge

c l o c k )

1

begin

//

S t a r t

o f s t a t e

F F s ( s t a t e

r e g i s t e r )

i f ( r e s e t n == 1 ’ b0 )

y Q <= A;

else

y Q <= Y D ;

end

//

End o f

s t a t e

F F s

( s t a t e r e g i s t e r )

// Output

l o g i c

// S e t z

t o 1 t o

t u r n on

LED

when i n

r e l e v a n t

s t a t e s

assign z

=

( ( y Q == ? ? ? )

j j

( y Q ==

???)); //

To be c o m p l e t e d by you !

endmodule

  • poly function.v

//Sw [ 7 : 0 ]

d a t a

i n

//KEY[ 0 ]

s y n c h r o n o u s r e s e t

when p r e s s e d

//KEY[ 1 ]

go

s i g n a l

//LEDR d i s p l a y s

r e s u l t

//HEX0 & HEX1

a l s o

d i s p l a y s

r e s u l t

module f p g a

t o p (SW,

KEY, CLOCK 50, LEDR, HEX0, HEX1) ;

input

[9:0]

SW;

input

[3:0]

KEY;

input CLOCK 50 ;

output

[9:0]

LEDR;

output

[6:0]

HEX0, HEX1;

wire r e s e t n ;

wire

go ;

wire

[7:0]

d a t a

r e s u l t ;

assign

go

= ~KEY[1];

assign

r e s e t n = KEY [ 0 ] ;

p a r t 2

u0 (

. c l k (CLOCK 50 ) ,

  • r e s e t n ( r e s e t n ) ,

  • go ( go ) ,

  • d a t a i n (SW[ 7 : 0 ] ) ,

. d a t a r e s u l t ( d a t a r e s u l t )

) ;

assign LEDR [ 9 : 0 ] = f2 ’ b00 , d a t a r e s u l t g;

h e x d e c o d e r H0(

. h e x d i g i t ( d a t a r e s u l t [ 3 : 0 ] ) ,

  • segments (HEX0) ) ;

h e x d e c o d e r H1(

. h e x d i g i t ( d a t a r e s u l t [ 7 : 4 ] ) ,

. segments (HEX1)

2

) ;

endmodule

module p a r t 2 (

input c l k ,

input r e s e t n ,

input

go ,

input

[7:0]

d a t a

i n ,

output

[7:0]

d a t a r e s u l t

) ;

// l o t s

o f w i r e s

t o

c o n n e c t

our

d a t a p a t h and c o n t r o l

wire

l d

a , l d b ,

l d

c ,

l d

x ,

l d

r ;

wire

l d

a l u o u t ;

wire

[1:0]

a l u

s e l e c t

a ,

a l u s e l e c t b ;

wire a l u o p ;

c o n t r o l

C0(

. c l k ( c l k ) ,

. r e s e t n ( r e s e t n ) ,

. go ( go ) ,

. l d a l u o u t ( l d a l u o u t ) ,

. l d

x ( l d

x ) ,

. l d

a ( l d

a ) ,

. l d

b ( l d

b ) ,

. l d

c ( l d

c ) ,

. l d

r ( l d

r ) ,

. a l u s e l e c t a ( a l u s e l e c t a ) ,

. a l u s e l e c t b ( a l u s e l e c t b ) ,

. a l u o p ( a l u o p )

) ;

datapath

D0(

. c l k ( c l k ) ,

. r e s e t n ( r e s e t n ) ,

. l d a l u o u t ( l d a l u o u t ) ,

. l d

x ( l d

x ) ,

. l d

a ( l d

a ) ,

. l d

b ( l d

b ) ,

. l d

c ( l d

c ) ,

. l d

r ( l d

r ) ,

. a l u s e l e c t a ( a l u s e l e c t a ) ,

. a l u s e l e c t b ( a l u s e l e c t b ) ,

. a l u o p ( a l u o p ) ,

. d a t a i n ( d a t a i n ) ,

. d a t a r e s u l t ( d a t a r e s u l t )

) ;

3

endmodule

module c o n t r o l (

input c l k ,

input r e s e t n ,

input go ,

output

reg

l d a ,

l d b , l d

c ,

l d

x ,

l d

r ,

output

reg

l d a l u

o u t ,

output

reg

[1:0]

a l u

s e l e c t

a

,

a l u

s e l e c t b ,

output

reg

a l u o p

) ;

reg [ 3 : 0 ]

c u r r e n t

s t a t e , n e x t

s t a t e ;

localparam

S LOAD A

=

4

d0

,

S LOAD A WAIT

=

4

d1

,

S LOAD B

=

4

d2

,

S LOAD B WAIT

=

4

d3

,

S LOAD C

=

4

d4

,

S LOAD C WAIT

=

4

d5

,

S LOAD X

=

4

d6

,

S LOAD X WAIT

=

4

d7

,

S CYCLE 0

=

4

d8

,

S CYCLE 1

=

4

d9

,

S CYCLE 2

=

4

d10 ;

// Next

s t a t e

l o g i c aka our

s t a t e

t a b l e

always@ ( )

begin :

s t a t e

t a b l e

case ( c u r r e n t

s t a t e )

S LOAD A:

n e x t

s t a t e

= go

? S LOAD A WAIT

: S LOAD A;

//

Loop

i n c u r r e n t

S LOAD A WAIT:

n e x t s t a t e = go ? S LOAD A WAIT

: S LOAD B; //

Loop i n c u r

S LOAD B:

n e x t

s t a t e

= go

? S LOAD B WAIT

: S LOAD B;

//

Loop

i n c u r r e n t

S LOAD B WAIT:

n e x t s t a t e = go ? S LOAD B WAIT

: S LOAD C; //

Loop i n c u r

S LOAD C:

n e x t

s t a t e

= go

? S LOAD C WAIT

: S LOAD C;

//

Loop

i n c u r r e n t

S LOAD C WAIT:

n e x t s t a t e = go ? S LOAD C WAIT

: S LOAD X; //

Loop i n c u r

S LOAD X:

n e x t

s t a t e

= go

? S LOAD X WAIT

: S LOAD X;

//

Loop

i n c u r r e n t

S LOAD X WAIT:

n e x t s t a t e

= go ? S LOAD X WAIT

: S CYCLE 0 ; // Loop i n c u

S CYCLE 0 :

n e x t

s t a t e

= S CYCLE 1;

S CYCLE 1 :

n e x t

s t a t e

= S LOAD A; //

we w i l l be

done

our

two

o p e r a t i o n s ,

default :

n e x t

s t a t e

= S LOAD A;

endcase

end //

s t a t e

t a b l e

// Output

l o g i c aka a l l o f

our

d a t a p a t h c o n t r o l

s i g n a l s

always @( )

begin :

e n a b l e s i g n a l s

//

By

d e f a u l t

make

a l l

our

s i g n a l s

0

l d a l u o u t = 1 ’ b0 ;

l d

a

=

1 ’ b0 ;

l d

b

=

1 ’ b0 ;

l d

c

=

1 ’ b0 ;

4

l d

x

=

1 ’ b0 ;

l d

r

=

1 ’ b0 ;

a l u s e l e c t

a

=

2

b00 ;

a l u s e l e c t

b

=

2

b00 ;

a l u

o p

=

1

b0 ;

case ( c u r r e n t

s t a t e )

S LOAD A : begin

l d

a

=

1

b1 ;

end

S LOAD B : begin

l d

b

=

1

b1 ;

end

S LOAD C : begin

l d

c

=

1

b1 ;

end

S LOAD X : begin

l d

x

=

1

b1 ;

end

S CYCLE 0 : begin

// Do A <

A A

l d a l u o u t = 1 ’ b1 ; l d a = 1 ’ b1 ; // s t o r e r e s u l t b a c k i n t o A

a l u

s e l e c t

a

=

2 ’ b00 ;

//

S e l e c t r e g i s t e r

A

a l u

s e l e c t

b

=

2 ’ b00 ;

//

Also s e l e c t r e g i s t e r A

a l u o p = 1 ’ b1 ; // Do m u l t i p l y o p e r a t i o n

end

S CYCLE 1 : begin

l d r =

1 ’ b1 ;

// s t o r e r e s u l t i n r e s u l t r e g i s t e r

a l u

s e l e c t

a

=

2 ’ b00 ;

//

S e l e c t r e g i s t e r

A

a l u

s e l e c t

b

=

2 ’ b10 ;

//

S e l e c t r e g i s t e r

C

a l u o p =

1 ’ b0 ;

// Do

Add

o p e r a t i o n

end

//

d e f a u l t :

//

don ’ t need

d e f a u l t s i n c e we a l r e a d y made s u r e a l l o f our o u t p u t

endcase

end //

e n a b l e

s i g n a l s

// c u r r e n t

s t a t e r e g i s t e r s

always@ ( posedge

c l k )

begin :

s t a t e

F F s

i f ( ! r e s e t n )

c u r r e n t

s t a t e <= S LOAD A ;

else

c u r r e n t s t a t e <= n e x t s t a t e ;

end // s t a t e

F F S

endmodule

module datapath (

input c l k ,

input r e s e t n ,

input

[7:0]

d a t a

i n ,

input

l d a l u

o u t ,

input

l d

x ,

l d a , l d b ,

l d

c ,

input

l d

r ,

input a l u o p ,

input

[1:0]

a l u

s e l e c t a

,

a l u s e l e c t

b ,

output

reg [ 7 : 0 ]

d a t a r e s u l t

5

) ;

// i n p u t r e g i s t e r s

reg

[7:0]

a , b ,

c , x ;

//

o u t p u t o f t h e a l u

reg

[7:0]

a l u o u t ;

//

a l u i n p u t muxes

reg

[7:0]

a l u a ,

a l u b ;

// R e g i s t e r s a , b , c , x w i t h r e s p e c t i v e i n p u t l o g i c

always @ ( posedge c l k ) begin

i f ( ! r e s e t n ) begin

  • <= 8 ’ d0 ; b <= 8 ’ d0 ; c <= 8 ’ d0 ; x <= 8 ’ d0 ;

end

else

begin

i f

( l d

a )

a <= l d a l u o u t ? a l u o u t : d a t a i n ; // l o a d a l u

o u t i f l o a d

a l u

o u t s i g n

i f

( l d b )

b <= l d a l u o u t ? a l u o u t : d a t a i n ; // l o a d a l u

o u t i f l o a d

a l u

o u t s i g n

i f

( l d

x )

x <=

d a t a

i n ;

i f

( l d

c )

c <=

d a t a

i n ;

end

end

// Output

r e s u l t

r e g i s t e r

always @

( posedge

c l k )

begin

i f ( ! r e s e t n )

begin

d a t a r e s u l t <= 8 ’ d0 ;

end

else

i f ( l d r )

d a t a r e s u l t <= a l u o u t ;

end

// The ALU i n p u t

m u l t i p l e x e r s

always @( )

begin

case

( a l u s e l e c t

a )

2 ’ d0 :

a l u

a

=

a ;

2 ’ d1 :

a l u

a

= b ;

2 ’ d2 :

a l u

a

=

c ;

2 ’ d3 :

a l u

a

=

x ;

default :

a l u

a

= 8 ’ d0 ;

endcase

6

case ( a l u

s e l e c t

b )

2 ’ d0 :

a l u

b

=

a ;

2 ’ d1 :

a l u

b

= b ;

2 ’ d2 :

a l u

b

=

c ;

2 ’ d3 :

a l u

b

=

x ;

default :

a l u

b

=

8

d0 ;

endcase

end

// The ALU

always @( )

begin

: ALU

//

a l u

case ( a l u o p )

0 :

begin

a l u o u t = a l u a + a l u b ; // p e r f o r m s a d d i t i o n

end

1 :

begin

a l u o u t = a l u a a l u b ; // p e r f o r m s m u l t i p l i c a t i o n

end

default :

a l u

o u t

=

8 ’ d0 ;

endcase

end

endmodule

module h e x

d e c o d e r ( h e x d i g i t ,

segments ) ;

input

[3:0]

h e x

d i g i t ;

output

reg

[6:0]

segments ;

always @( )

case ( h e x

d i g i t )

4 ’ h0 :

segments

=

7

b100 0000 ;

4 ’ h1 :

segments

=

7

b111 1001 ;

4 ’ h2 :

segments

=

7

b010 0100 ;

4 ’ h3 :

segments

=

7

b011 0000 ;

4 ’ h4 :

segments

=

7

b001 1001 ;

4 ’ h5 :

segments

=

7

b001 0010 ;

4 ’ h6 :

segments

=

7

b000 0010 ;

4 ’ h7 :

segments

=

7

b111 1000 ;

4 ’ h8 :

segments

=

7

b000 0000 ;

4 ’ h9 :

segments

=

7

b001 1000 ;

4 ’hA :

segments

=

7

b000 1000 ;

4 ’hB :

segments

=

7

b000 0011 ;

4 ’hC :

segments

=

7

b100 0110 ;

4 ’hD :

segments

=

7

b010 0001 ;

4 ’hE :

segments

=

7

b000 0110 ;

4 ’ hF :

segments

=

7

b000 1110 ;

default :

segments

= 7 ’ h 7 f ;

7

endcase

endmodule

8