Register Transfer Level - mbits-mirafra/digitalDesignCourse GitHub Wiki

RTL DESIGN

What is RTL design?

  • RTL design or Register Transfer Level design is a method by which we can transfer data from one register to another
  • RTL (Register-Transfer Level) design is a methodology used in digital circuit design that describes the behavior of a digital circuit at the register-transfer level of abstraction
  • This means that the digital circuit is described in terms of registers, transfer functions, and combinational logic
  • Constructing a digital design using Combinational and Sequential circuits in HDL like Verilog or VHDL which can model logical and hardware operation

Why RTL is needed?

  • For understanding the complex operation performed in any digital systems we should understand RTL first
  • RTL design allows designers to create digital circuits that are easier to understand, debug, and verify
  • It also allows for faster design iteration, as changes can be made at the RTL level rather than requiring changes to be made at the gate level
  • Register-transfer-level abstraction is used in HDL to create high-level representations of a circuit, from which lower-level representations and ultimately actual wiring can be derived

When to use RTL design?

As long as the system is simple there will not be any problem with the design but as the design becomes more complex we need to partition the whole system into smaller subsystems called modules. Modules are constructed using registers, multiplexers, decoders, etc. At this time RTL design is used.

RTL (Register-Transfer Level) design is a digital design technique used to create complex digital circuits. Here are a few examples of RTL design:

  1. Adder/Subtractor: An RTL design of an adder/subtractor circuit can perform both addition and subtraction operations on binary numbers
  2. Finite State Machine (FSM): RTL designs of FSMs are commonly used in digital systems that require sequential logic, such as in control units of processors
  3. Multiplexer (MUX): An RTL design of a multiplexer selects one input from multiple inputs based on the control signals

RTL Architecture

RTL design tools:

  • Xilinx/AMD- Vivado
  • Intel /Altera -Quartus
  • Synopsys -RTL Architect
  • Cadence -Genus

RTL method uses a set of expressions and statements to resemble the statements used in the programming language. In digital systems if we have to perform any operation we have to specify some things:

  • Set of registers in the system.
  • Binary–coded information in the registers.
    • Inter register transfer operation
    • Arithmetic operation
    • Logical operation
    • Shift operation
  • Control functions.

Let us consider an example :

And Gate

module behavioral_and(input a,input b,output reg y );

always @(*) begin
if (a && b) begin // if both inputs are 1
    y = 1; // output is 1
end
else begin // if either input is 0
    y = 0; // output is 0
end
end

endmodule

and

Or Gate

module OR_2_behavioral (output reg Y, input A,input B);
always @ (A or B) begin
if (A == 1'b0 & B == 1'b0) begin
    Y = 1'b0;
end
else 
    Y = 1'b1; 
end
endmodule

or

Nand gate

module NOR_2_behavioral (output reg Y, input A, input B);
always @ (A or B) begin
if (A == 1'b0 & B == 1'b0) begin
    Y = 1'b1;
end
else 
    Y = 1'b0; 
end
endmodule

Nor gate

module NOR_2_behavioral (output reg Y,input A,input B);
always @ (A or B) begin
if (A == 1'b0 & B == 1'b0) begin
    Y = 1'b1;
end
else 
    Y = 1'b0; 
end
endmodule

Not gate

module not_gate(input a, output reg y);

always @(a) 
begin
if(a == 1'b0)
begin 
y = 1b'1;
end
else
y = 1b'0;
end

endmodule

2:1 Mux

module mux2_1(sel,inp,out);
input sel;
input [1:0] inp;
output reg out;
always @(*)
begin
case(sel)
    1'b0 : out = inp[o];
    1'b1 : out = inp[1];
    endcase
end
endmodule

4:1 Mux

module mux4_1(sel,inp,out);
input [1:0]sel;
input [3:0]inp;
output reg out;
always @(*)
begin
case(sel)
    2'b00 : out = inp[o];
    2'b01 : out = inp[1];
    2'b10 : out = inp[2];
    2'b11 : out = inp[3];
    endcase
end
endmodule

8:1 Mux

module mux8_1(sel,inp,out);
input [2:0]sel;
input [7:0]inp;
output reg out;
always @(*)
begin
case(sel)
    3'b000 : out = inp[o];
    3'b001 : out = inp[1];
    3'b010 : out = inp[2];
    3'b011 : out = inp[3];
    3'b100 : out = inp[4];
    3'b101 : out = inp[5];
    3'b110 : out = inp[6];
    3'b111 : out = inp[7];
    endcase
end
endmodule

1:2 Demux

module demux1_2(sel, A, out);
input sel, A;
output [1:0] out;
always @(*)
begin    
case(sel)
    1'b0 : out[0] = A;
    1'b1 : out[1] = A;
endcase
end
endmodule

1:4 Demux

module demux1_4(sel, A, out);
input [1:0] sel;
input A;
output reg [3:0] out;
always @(*)
begin    
case(sel)
    2'b00 : out[0] = A;
    2'b01 : out[1] = A;
    2'b10 : out[2] = A;
    2'b11 : out[3] = A;
endcase
end
endmodule

1:8 Demux

module demux1_8(sel, A, out);
input [2:0] sel;
input A;
output reg [7:0] out;
always @(*)
begin    
case(sel)
    3'b000 : out[0] = A;
    3'b001 : out[1] = A;
    3'b010 : out[2] = A;
    3'b011 : out[3] = A;
    3'b100 : out[4] = A;
    3'b101 : out[5] = A;
    3'b110 : out[6] = A;
    3'b111 : out[7] = A;
endcase
end
endmodule

Half Adder

module half_adder(a,b,sum,cout);
input a,b;
output reg sum,cout; // sum and carry

always @(*)
begin 
case ({a,b})
2'b00: sum = 0;
2'b01: sum = 1;
2'b10: sum = 1;
2'b11: sum = 0;
default : sum = 0;
endcase 

case ({a,b})
2'b00: cout = 0;
2'b01: cout = 0;
2'b10: cout = 0;
2'b11: cout = 1;
default : cout = 0;
endcase 
end  
endmodule

Full Adder

module full_adder(input a,input b,input cin,output reg s,output reg cout);

always @(a or b or cin) begin
// Truth table for the sum output
case ({a, b, cin})
  3'b000: s = 1'b0;
  3'b001: s = 1'b1;
  3'b010: s = 1'b1;
  3'b011: s = 1'b0;
  3'b100: s = 1'b1;
  3'b101: s = 1'b0;
  3'b110: s = 1'b0;
  3'b111: s = 1'b1;
endcase

// Truth table for the carry out output
case ({a, b, cin})
  3'b000: cout = 1'b0;
  3'b001: cout = 1'b0;
  3'b010: cout = 1'b0;
  3'b011: cout = 1'b1;
  3'b100: cout = 1'b0;
  3'b101: cout = 1'b1;
  3'b110: cout = 1'b1;
  3'b111: cout = 1'b1;
endcase
end

endmodule

Half Subtractor

module half_subtractor(a,b,diff,borrow);
input a,b;
output reg diff,borrow;

always @(*)
begin 
case ({a,b})
2'b00: diff = 0;
2'b01: diff = 1;
2'b10: diff = 1;
2'b11: diff = 0;
default : diff = 0;
endcase 

case ({a,b})
2'b00: borrow = 0;
2'b01: borrow = 1;
2'b10: borrow = 0;
2'b11: borrow = 0;
default : borrow = 0;
endcase 
end  
endmodule

Full Subtractor

module full_subtractor(input a,input b,input bin,output reg d, output reg bout);

always @(a or b or bin) 
begin
case ({a, b, bin})
  3'b000: d = 1'b0;
  3'b001: d = 1'b1;
  3'b010: d = 1'b1;
  3'b011: d = 1'b0;
  3'b100: d = 1'b1;
  3'b101: d = 1'b0;
  3'b110: d = 1'b0;
  3'b111: d = 1'b1;
endcase

case ({a, b, bin})
  3'b000: bout = 1'b1;
  3'b001: bout = 1'b1;
  3'b010: bout = 1'b1;
  3'b011: bout = 1'b0;
  3'b100: bout = 1'b0;
  3'b101: bout = 1'b0;
  3'b110: bout = 1'b0;
  3'b111: bout = 1'b1;
endcase
end

endmodule

SR Flip Flop

module srff_behave(s,r,clk, q, qbar);
input s,r,clk;
output reg q, qbar;

always@(posedge clk)
begin

if(s == 1)
begin
q = 1;
qbar = 0;
end
else if(r == 1)
begin
q = 0;
qbar =1;
end
else if(s == 0 & r == 0) 
begin 
q <= q;
qbar <= qbar
end
end
endmodule

D Flip Flop

module dff (clk, reset, d, q, qb);
input clk;
input reset;
input d;
output q;
output qb;
reg q;
assign qb = ~q;
always @(posedge clk or posedge reset)
begin
if (reset)
begin
q <= 1'b0;
end
else
begin
q <= d;
end
end
endmodule

JK Flip Flop

module jk_flip_flop(input j,input k,input clk,output reg q);

always @(posedge clk) begin
if (j && ~k) // Set
q <= 1'b1;
else if (~j && k) // Reset
q <= 1'b0;
else if (j && k) // Toggle
q <= ~q;
end

endmodule

T Flip Flop

module t_flip_flop(input t,input clk,output reg q );
always @(posedge clk) begin
if (t) // Toggle
q <= ~q;
end
endmodule

ALU

module alu( input [31:0] a,b, input [2:0] o, input e,output [31:0] aluout );
reg [31:0] aluresult;
assign aluout=aluresult;
always@(*) begin
if(e) begin
case(o)
3'b000: aluresult=a+b;
3'b001: aluresult=a-b;
3'b010: aluresult=a+1;
3'b011: aluresult=a-1;
3'b100: aluresult=a;
3'b101: aluresult=~a;
3'b110: aluresult=a|b; 
3'b111: aluresult=a&b;
endcase
end
else
aluresult=32'bz;
end
endmodule

alu