Feineigle.com - Digital Design - An Embedded Systems Approach Using VHDL

Home · Book Reports · 2017 · Digital Design - An Embedded Systems Approach Using VHDL

Published: December 27, 2017 (6 years 3 months ago.)
Tags:  Electronics · Hardware · Software · VHDL



The book in...
One sentence:
A nice balance between low level gate logic and higher level abstractions as well as enough general design concepts to whet your pallet just enough to set you toward a more advance book covering one of many topics discussed.

Five sentences:
The book assumes a basic understanding of the general principals, concepts, and components of electrical engineering. These basic concepts are expanded upon with more detailed descriptions of digital logic/boolean algebra and slightly more abstracted complex components like flip-flops. These abstractions are introduced and modeled, usually in a well described UML style presentation, and then converted into VHDL. As it progresses, the book combines all of the aforementioned into more complex designs that include finite state machines, soft cores, memories, accelerators, etc. Before a final review of the design process, a case study is presented for the design of a pipelined implementation of a sobel filter video accelerator.

designates my notes. / designates important.


Thoughts

After finishing the Bruce Land/Cornell FPGA/Verilog course, ECE5760 (2011), I found out that there is a new version available for 2017. I haven’t gone through the 2017 version yet, but assuming they are similar to the 2011 version, they will be worthwhile.

I did work my way through the first 30 or so videos of the VHDL tutorial from LBE Books while reading this. These cover a few of the topics skipped by this book, particularly Karnaugh Maps and Quine-McClusky minimization. As with anything, you will learn more by doing than reading. These are short and sweet and great practice fodder to try to implement yourself without looking back at the video.

This book is a good compromise between low level gate logic and higher level abstraction. Definitely not the first book you want to pick up on electrical engineering or VHDL, but if you have a solid understanding of EE and a software foundation to approach the VHDL component for, it is a worthwhile book.

We have now completed our foundational study of digital system design. We started with the basic elements of digital logic, gates and flip-flops, and showed how they can be used in circuits that meet given functional requirements. Given the complexity of requirements for most modern systems, we appealed to the principle of abstraction as a means of managing complexity. In particular, we use hierarchical composition to build blocks from the primitive elements, and systems from those blocks. By this means, we were able to reach the level of complete embedded systems, comprising processors, memories, I/O controllers, and accelerators, without becoming overwhelmed by the detailed interactions of the millions of transistors involved. Throughout our study, we also paid attention to the design methodology real-world effects that arise in digital circuits and the constraints that they imply. We showed how a disciplined design methodology helps us meet functional requirements while satisfying constraints. The study of digital systems in this book serves as a foundation for further studies in several areas.

Other references that may be of interest:


Table of Contents


· CHAPTER 1: Introduction and Methodology

page 21:
page 28:
page 29:
page 32:
page 34:

· CHAPTER 2: Combinational Basics

page 41:
page 48:
page 49:
page 52:
page 56:
page 61:
page 72:
page 79:

· CHAPTER 3: Numeric Basics

page 91:
ieee.numeric_std.all;
page 94:
0: 0000
1: 0001
2: 0010
3: 0011
4: 0100
5: 0101
6: 0110
7: 0111
8: 1000
9: 1001
A: 1010
B: 1011
C: 1100
D: 1101
E: 1110
F: 1111
page 97:
y <= resize(x, 8);
and
x <= resize(y, 4);
page 106:
page 107:
page 113:
page 114:
page 116:
shift_left(s, 2)
shift_right(s,2)
page 117:
page 123:
What values are represented by the 8-bit 2s-complement numbers 00110101 and
10110101?

Solution
The first number is:
1 x 2^5 + 1 x 2^4 + 1 x 2^2 + 1 x 2^0 = 32 + 16 + 4 + 1 = 53
The second number is;
-1 x 2^7 + 1 x 2^5 + 1 x 2^4 + 1 x 2^2 + 1 x 2^0 = -128 + 32 + 16 + 4 + 1 = -75
page 124:
signal n1, n2 : integer                 -- implies an
                range 2**7 to 2**71;  -- 8-bit range
signal x, y : signed( 7 downto 0);
signal z : signed(11 downto 0);
signal z_sign : std_logic;
n1 <= to_integer(x);
n2 <= n1 + to_integer(y);
z <= to_signed(n2, z'length);
z_sign <= z(z'left);
page 126:
page 127:
signal x : signed( 7 downto 0);
signal y : signed(15 downto 0);

we can write the following assignment statement in an architecture to sign
extend the value of x and assign it to y:

y <= resize(x, y'length);

Similarly, we can write the following assignment to truncate the value of
y and assign it to x:

x <= resize(y, x'length);
page 128:
page 130:
signal v1, v2 : signed(11 downto 0);
signal sum : signed(12 downto 0);

we can add the two 12-bit values and get a 13-bit result using the assignment

sum <= resize(v1, sum'length) + resize(v2, sum'length);
signal x, y, z : signed(7 downto 0);
signal ovf : std_logic;

we can write the following assignments to derive the required sum and
overflow condition bit:

z <= x + y;
ovf <= ( not x(7) and not y(7) and z(7) ) or
       ( x(7) and y(7) and not z(7) );
page 131:
signal v1, v2 : signed(11 downto 0);
signal diff : signed(12 downto 0);

we can calculate the 13-bit difference between the two 12-bit values using
the assignment

diff <= resize(v1, diff'length)  resize(v2, diff'length);
signal x, y, z : signed(7 downto 0);
signal ovf : std_logic;

we can write the following assignments to derive the required difference
and overflow condition bit:

z <= x  y;
ovf <= ( not x(7) and y(7) and z(7) ) or
       ( x(7) and not y(7) and not z(7) );
page 135:
Example 3.18 
What number is represented by the fixed-point binary number 01100010, assuming
the binary point is four places from the right?

solution
The number is 0110.00102
= 0x2^3 + 1x2^2 + 1x2^1 + 0x2^0 + 0x2^-1 + 0x2^-2 + 1x2^-3 + 0x2^-4
= 0 + 4 + 2 + 0 + 0 + 0 + 1/8 + 0 = 6.125_10
page 136:
Example 3.19
 What number is represented by the signed fixed-point
binary number 111101, assuming the binary point is four places from the right?

solution
The number is 11.11012
= -1x2^1 + 1x2^0 + 1x2^-1 + 1x2^-2 + 0x2^-3 + 1x2^-4
= -2 + 1 + 1/2 + 1/4 + 0 + 1/16 = -0.1875_10
page 138:
page 142:
page 145:
signal fp_num : float(5 downto 10);
page 146:
page 148:
page 159:

· CHAPTER 4: Sequential Basics

page 164:
reg: process (clk) is
begin
  if rising_edge(clk) then
    if reset = '1' then
      q <= '0';
    elsif ce = '1' then
      q <= d;
    end if;
  end if;
end process reg;
reg: process (clk, reset) is
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    if ce = '1' then
      q <= d;
    end if;
  end if;
end process reg;
page 168:
page 170:
page 172:
page 183:
page 185:
page 187:
library ieee;
use ieee.std_logic_1164.all, ieee.fixed_pkg.all;
entity multiplier is
  port (clk, reset: in std_logic;
        input_rdy: in std_logic;
        a_r, a_i, b_r, b_i: in sfixed(3 downto 12);
        p_r, p_i: out sfixed(7 downto 24) );
end entity multiplier;

architecture rtl of multiplier is
  signal a_sel, b_sel,
         pp1_ce, pp2_ce,
         sub, p_r_ce, p_i_ce : std_logic;
  signal a_operand, b_operand : sfixed(3 downto 12);
  signal pp, pp1, pp2, sum : sfixed(7 downto 24);

begin
  a_operand <= a_r when a_sel = '0' else a_i;
  b_operand <= b_r when b_sel = '0' else b_i;
  pp <= a_operand * b_operand;

pp1_reg : process (clk) is
begin
  if rising_edge(clk) then
    if pp1_ce = '1' then
      pp1 <= pp;
    end if;
  end if;
end process pp1_reg;

pp2_reg : process (clk) is
begin
  if rising_edge(clk) then
    if pp2_ce = '1' then
      pp2 <= pp;
    end if;
  end if;
end process pp2_reg;

sum <= pp1 + pp2 when sub = '0' else pp1  pp2;

p_r_reg : process (clk) is
begin
  if rising_edge(clk) then
    if p_r_ce = '1' then
      p_r <= sum;
    end if;
  end if;
end process p_r_reg;

p_i_reg : process (clk) is
begin
  if rising_edge(clk) then
    if p_i_ce = '1' then
      p_i <= sum;
    end if;
  end if;
end process p_i_reg;

end architecture rtl;
1. Multiply a_r and b_r, and store the result in partial product register 1.
2. Multiply a_i and b_i, and store the result in partial product register 2.
3. Subtract the partial product register values and store the result in the
product real part register.
4. Multiply a_r and b_i, and store the result in partial product register 1.
5. Multiply a_i and b_r, and store the result in partial product register 2.
6. Add the partial product register values and store the result in the product
imaginary part register.
page 188:
page 190:
page 191:
type multiplier_state is
  (step1, step2, step3, step4, step5);

signal current_state : multiplier_state;

current_state <= step4;
page 192:
type multiplier_state is (step1, step2, step3, step4, step5);
signal current_state, next_state : multiplier_state;

state_reg : process (clk, reset) is
begin
  if reset = '1' then
    current_state <= step1;
  elsif rising_edge(clk) then
    current_state <= next_state;
  end if;
end process state_reg;

next_state_logic : process (current_state, input_rdy) is
begin
  case current_state is
    when step1 =>
      if input_rdy = '0' then
        next_state <= step1;
      else
        next_state <= step2;
      end if;
    when step2 =>
      next_state <= step3;
    when step3 =>
      next_state <= step4;
    when step4 =>
      next_state <= step5;
    when step5 =>
      next_state <= step1;
  end case;
end process next_state_logic;

output_logic : process (current_state) is
begin
  a_sel <= '0'; b_sel <= '0'; pp1_ce <= '0'; pp2_ce <= '0';
  sub <= '0'; p_r_ce <= '0'; p_i_ce <= '0';
  case current_state is
    when step1 =>
      pp1_ce <= '1';
    when step2 =>
      a_sel <= '1'; b_sel <= '1'; pp2_ce <= '1';
    when step3 =>
      b_sel <= '1'; pp1_ce <= '1'; sub <= '1'; p_r_ce <= '1';
    when step4 =>
      a_sel <= '1'; pp2_ce <= '1';
    when step5 =>
      p_i_ce <= '1';
  end case;
end process output_logic;
page 196:
page 197:
page 198:
t_co + t_pd + t_su < t_c
t_co + t_pd-s + t_pd-o + t_pd-c + t_su < t_c
page 204:
page 205:
library ieee; use ieee.std_logic_1164.all;
entity debouncer is
  port (clk, reset: in std_logic;
        pb: in std_logic;
        pb_debounced : out std_logic );
end entity debouncer;

architecture rtl of debouncer is
signal count500000 : integer range 0 to 499999;
signal clk_100Hz : std_logic;
signal pb_sampled
 : std_logic;
begin

div_100Hz : process (clk, reset) is
begin
  if reset = '1' then
    count500000 <= 499999;
  elsif rising_edge(clk) then
    if clk_100Hz = '1' then
      count500000 <= 499999;
    else
      count500000 <= count500000  1;
    end if;
  end if;
end process div_100Hz;

clk_100Hz <= '1' when count500000 = 0 else '0';

debounce_pb : process (clk) is
begin
  if rising_edge(clk) then
    if clk_100Hz = '1' then
      if pb = pb_sampled then
        pb_debounced <= pb;
      end if;
      pb_sampled <= pb;
    end if;
  end if;
end process debounce_pb;
end architecture rtl;
page 206:
page 213:
page 214:
page 215:

· CHAPTER 5: Memories

page 228:
page 229:
page 231:
page 232:
page 233:
page 236:
type RAM_4Kx16 is array (0 to 4095) of std_logic_vector(15 downto 0);
signal data_RAM : RAM_4Kx16;
data_RAM_flow_through : process (clk) is
begin
  if rising_edge(clk) then
    if en = '1' then
      if wr = '1' then
        data_RAM(to_integer(a)) <= d_in; d_out <= d_in;
      else
        d_out <= data_RAM(to_integer(a));
      end if;
    end if;
  end if;
end process data_RAM_flow_through;
page 241:
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;

entity dual_port_SSRAM is
  port (clk: in std_logic;
        en1, wr1 : in std_logic;
        a1: in unsigned(11 downto 0);
        d_in1: in std_logic_vector(15 downto 0);
        d_out1: out std_logic_vector(15 downto 0);
        en2: in std_logic;
        a2: in unsigned(11 downto 0);
        d_out2: out std_logic_vector(15 downto 0) );
end entity dual_port_SSRAM;

architecture synth of dual_port_SSRAM is
  type RAM_4Kx16 is array (0 to 4095) of std_logic_vector(15 downto 0);
  signal data_RAM : RAM_4Kx16;
begin

read_write_port : process (clk) is
begin
  if rising_edge(clk) then
    if en1 = '1' then
      if wr1 = '1' then
        data_RAM(to_integer(a1)) <= d_in1; d_out1 <= d_in1;
      else
        d_out1 <= data_RAM(to_integer(a1));
      end if;
    end if;
  end if;
end process read_write_port;

read_only_port : process (clk) is
begin
  if rising_edge(clk) then
    if en2 = '1' then
      d_out2 <= data_RAM(to_integer(a2));
    end if;
  end if;
end process read_only_port;
end architecture synth;
page 243:
page 246:
page 247:
library ieee; use ieee.numeric_std.all;
architecture ROM_based of seven_seg_decoder is
  type ROM_array is array (0 to 31) of std_logic_vector(7 downto 1);
  constant ROM_content : ROM_array := 
    ( 0 => "0111111", 1 => "0000110",
      2 => "1011011", 3 => "1001111",
      4 => "1100110", 5 => "1101101",
      6 => "1111101", 7 => "0000111",
      8 => "1111111", 9 => "1101111",
      10 to 15 => "1000000",
      16 to 31 => "0000000" );

begin
  seg <= ROM_content(to_integer(unsigned(blank & bcd)));
end architecture ROM_based;
page 248:
type ROM_512x20 is array (0 to 511) of std_logic_vector(19 downto 0);
constant data_ROM : ROM_512x20 := (X"00000", X"0126F", ...);

FPGA_ROM : process (clk) is
begin
  if rising_edge(clk) then
    if en = '1' then
      d_out <= data_ROM(to_integer(a));
    end if;
  end if;
end process FPGA_ROM;
page 252:
page 253:
page 254:

· CHAPTER 6: Implementation Fabrics

page 267:
page 276:
page 277:
page 285:
page 288:

· CHAPTER 7: Processor Basics

page 294:
page 295:
page 296:
page 297:
page 298:
page 314:
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
entity gumnut is
port (clk_i: in std_logic;
      rst_i: in std_logic;
      inst_cyc_o: out std_logic;
      inst_stb_o: out std_logic;
      inst_ack_i: in std_logic;
      inst_adr_o: out unsigned(11 downto 0);
      inst_dat_i: in std_logic_vector(17 downto 0);
      data_cyc_o: out std_logic;
      data_stb_o: out std_logic;
      data_we_o: out std_logic;
      data_ack_i: in std_logic;
      data_adr_o: out unsigned(7 downto 0);
      data_dat_o: out std_logic_vector(7 downto 0);
      data_dat_i: in std_logic_vector(7 downto 0)
     );
end entity gumnut;
architecture rtl of embedded_gumnut is
type ROM_2Kx18 is array (0 to 2047) of std_logic_vector(17 downto 0);
constant instr_ROM : ROM_2Kx18 := ( ... );
type RAM_256x8 is array (0 to 255) of std_logic_vector(7 downto 0);

signal data_RAM : RAM_256x8;
signal clk : std_logic;
signal rst : std_logic;
signal inst_cyc_o : std_logic;
signal inst_stb_o : std_logic;
signal inst_ack_i : std_logic;
signal inst_adr_o : unsigned(11 downto 0);
signal inst_dat_i : std_logic_vector(17 downto 0);
signal data_cyc_o : std_logic;
signal data_stb_o : std_logic;
signal data_we_o : std_logic;
signal data_ack_i : std_logic;
signal data_adr_o : unsigned(7 downto 0);
signal data_dat_o : std_logic_vector(7 downto 0);
signal data_dat_i : std_logic_vector(7 downto 0);

begin
  CPU : entity work.gumnut
    port map (clk_i => clk,
              rst_i => rst,
              inst_cyc_o => inst_cyc_o,
              inst_stb_o => inst_stb_o,
              inst_ack_i => inst_ack_i,
              inst_adr_o => inst_adr_o,
              inst_dat_i => inst_dat_i,
              data_cyc_o => data_cyc_o,
              data_stb_o => data_stb_o,
              data_we_o => data_we_o,
              data_ack_i => data_ack_i,
              data_adr_o => data_adr_o,
              data_dat_o => data_dat_o,
              data_dat_i => data_dat_i
             );

  IMem : process (clk) is
    begin
    if rising_edge(clk) then
      if inst_cyc_o = '1' and inst_stb_o = '1' then
        inst_dat_i <= instr_ROM(to_integer(inst_adr_o(10 downto 0)));
        inst_ack_i <= '1';
      else
        inst_ack_i <= '0';
      end if;
    end if;
    end process IMem;

  DMem : process (clk) is
  begin
  if rising_edge(clk) then
    if data_cyc_o = '1' and data_stb_o = '1' then
      if data_we_o = '1' then
        data_RAM(to_integer(data_adr_o)) <= data_dat_o;
        data_dat_i <= data_dat_o;
        data_ack_i <= '1';
      else
        data_dat_i <= data_RAM(to_integer(data_adr_o));
        data_ack_i <= '1';
      end if;
    end if;
  end if;
  end process DMem;

end architecture rtl;
page 320:
page 321:
page 324:

· CHAPTER 8: I/O Interfacing

page 335:
page 341:
page 342:
page 351:
page 356:
page 366:
page 368:
page 369:
page 370:
page 372:
page 377:
page 378:
library ieee;
use ieee.std_logic_1164.all;
entity sensor_controller is
port (clk_i, rst_i : in std_logic;
      cyc_i, stb_i : in std_logic;
      ack_o : out std_logic;
      dat_o : out std_logic_vector(7 downto 0);
      int_req : out std_logic;
      int_ack : in std_logic;
      sensor_in : in std_logic_vector(7 downto 0) );
end entity sensor_controller;

architecture rtl of sensor_controller is
signal prev_data, current_data : std_logic_vector(7 downto 0);
signal current_int_req : std_logic;

begin
data_regs : process (clk_i) is
begin
  if rising_edge(clk_i) then
    if rst_i = '1' then
      prev_data <= "00000000";
      current_data <= "00000000";
    else
      prev_data <= current_data;
      current_data <= sensor_in;
    end if;
  end if;
end process data_regs;

int_state : process (clk_i) is
begin
  if rising_edge(clk_i) then
    if rst_i = '1' then
      current_int_req <= '0';
    else
      case current_int_req is
        when '0' =>
          if current_data /= prev_data then
            current_int_req <= '1';
          end if;
        when others =>
          if int_ack = '1' then
            current_int_req <= '0';
          end if;
      end case;
    end if;
  end if;
end process int_state;

dat_o <= current_data;
int_req <= current_int_req;
ack_o <= cyc_i and stb_i;
end architecture rtl;
page 381:
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
entity real_time_clock is
  port (clk_i, rst_i : in std_logic; -- 50 MHz clock
        cyc_i, stb_i, we_i : in std_logic;
        ack_o : out std_logic;
        adr_i : in std_logic;
        dat_i : in unsigned(7 downto 0);
        dat_o : out unsigned(7 downto 0);
        int_req : out std_logic );
end entity real_time_clock;

architecture rtl of real_time_clock is
  constant clk_freq : natural := 50000000;
  constant timebase_freq : natural := 100000;
  constant timebase_divisor : natural := clk_freq / timebase_freq;
  signal count_value : unsigned(7 downto 0);
  signal trigger_interrupt : std_logic;
  signal int_enabled, int_triggered : std_logic;

begin
  counter : process (clk_i) is
    variable timebase_count : natural range 0 to timebase_divisor  1;
    variable count_start_value : unsigned(7 downto 0);

  begin
    if rising_edge(clk_i) then
      if rst_i = '1' then
        timebase_count := 0;
        count_start_value := "00000000";
        count_value <= "00000000";
        trigger_interrupt <= '0';
      elsif cyc_i = '1' and stb_i = '1' and adr_i = '0' and we_i = '1' then
        timebase_count := 0;
        count_start_value := dat_i;
        count_value <= dat_i;
        trigger_interrupt <= '0';
      elsif timebase_count = timebase_divisor  1 then
        timebase_count := 0;
        if count_value = "00000000" then
          count_value <= count_start_value;
          trigger_interrupt <= '1';
        else
          count_value <= count_value  1;
          trigger_interrupt <= '0';
      end if;
    else
      timebase_count := timebase_count + 1;
      trigger_interrupt <= '0';
    end if;
  end if;
end process counter;

control_reg : process (clk_i) is
begin
  if rising_edge(clk_i) then
    if rst_i = '1' then
      int_enabled <= '0';
    elsif cyc_i = '1' and stb_i = '1' and adr_i = '1' and we_i = '1' then
      int_enabled <= dat_i(0);
    end if;
  end if;

end process control_reg;

int_reg : process (clk_i) is
begin
  if rising_edge(clk_i) then
    if rst_i = '1' or (cyc_i = '1' and stb_i = '1' and adr_i = '1' and we_i = '0') then
      int_triggered <= '0';
    elsif trigger_interrupt = '1' then
      int_triggered <= '1';
    end if;
  end if;
end process int_reg;

dat_o <= count_value when adr_i = '0' else "0000000" & int_triggered;
int_req <= int_triggered and int_enabled;
ack_o <= cyc_i and stb_i;
end architecture rtl;
page 387:
page 392:

· CHAPTER 9: Accelerators

page 395:
page 396:
page 400:
page 405:
page 416:

“width:33%; margin:1%;”)}}

page 436:

· CHAPTER 10: Design Methodology

page 460:
page 463:
page 465:

Appendix C

page 564:
type state_type is (state1, state2, state3, state4);
signal current_state, next_state : state_type;


state_reg : process (clock) is
begin
  if rising_edge(clock) then
    if reset = '1' then
      current_state <= initial-state;
    else
      current_state <= next_state;
    end if;
  end if;
end process state_reg;

next_state_logic : process (current_state,
input-1, input-2, ...) is
begin
  case current_state is
    when state1 =>
      if condition-1 then
        next_state <= state-value;
      elsif condition-2 then
        next_state <= state-value;
        ...
      else
        next_state <= state-value;
      end if;
    when state2 =>
    ...
  end case;
end process next_state_logic;

output_logic : process (current_state, input-1, input-2, ...) is
begin
  case current_state is
    when state1 =>
      moore-output-1 <= value; moore-output-2 <= value; ...
      if condition-1 then
        mealy-output-1 <= value; mealy-output-2 <= value; ...
      elsif condition-2 then
        mealy-output-1 <= value; mealy-output-2 <= value; ...
        ...
      else
        mealy-output-1 <= value; mealy-output-2 <= value; ...
      end if;
    when state2 =>
      ...
  end case;
end process output_logic;

fsm_logic : process (current_state, input-1, input-2, ...) is
begin
  case current_state is
    when state1 =>
      if condition-1 then
        next_state <= state-value;
        mealy-output-1 <= value; mealy-output-2 <= value; ...
      elsif condition-2 then
        next_state <= state-value;
        mealy-output-1 <= value; mealy-output-2 <= value; ...
        ...
      else
        next_state <= state-value;
        mealy-output-1 <= value; mealy-output-2 <= value; ...
      end if;
      moore-output-1 <= value; moore-output-2 <= value; ...
    when state2 =>
      ...
  end case;
end process fsm_logic;
page 567:
process-name : process (clock) is
begin
  if rising_edge(clock) then
    if enable = '1' then
      if write = '1' then
        data_ram(to_integer(address)) <= data-in;
        data-out <= data-in;
      else
        data-out <= data_ram(to_integer(address));
      end if;
    end if;
  end if;
end process process-name;
type rom_type is array (0 to 128) of unsigned(11 downto 0);
constant data_rom : rom_type := (X"000", X"021", X"1B3", X"7C0", ...);

data-out <= data_rom(to_integer(address));

OR

process-name : process (clock) is
  begin
  if rising_edge(clock) then
    if enable = '1' then
      data-out <= data_rom(to_integer(address));
    end if;
  end if;
end process process-name;