Description |
System Verilog |
Verilog |
VHDL |
HDL Example 4.1 COMBINATIONAL LOGIC
HDL Example 4.1 illustrates behavioral descriptions of a module that computes the Boolean function y = ~a & ~b & ~c | a & ~b & ~c | a & ~b & c ~ - not & - and | - or
|
module sillyfunction_sv ( input logic a, b, c, output logic y ); assign y = ~a & ~b & ~c | a & ~b & ~c | a & ~b & c; endmodule |
module sillyfunction_v ( input a, b, c, output y ); assign y = ~a & ~b & ~c | a & ~b & ~c | a & ~b & c; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity sillyfunction_vhd is
port ( a, b, c: in STD_LOGIC; y: out STD_LOGIC ); end;
architecture synth of sillyfunction_vhd is begin y <= (not a and not b and not c) or (a and not b and not c) or (a and not b and c); end;
|
HDL Example 4.2 INVERTERS
HDL Example 4.2 describes four inverters connected to 4-bit busses. Bitwise operators
|
module inv_sv ( input logic [3:0] a, output logic [3:0] y );
assign y = ~a;
endmodule
|
module inv_v
( input [3:0] a, output [3:0] y );
assign y = ~a;
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity inv_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth of inv_vhd is begin y <= not a; end;
|
HDL Example 4.3 LOGIC GATES
HDL Example 4.3 demonstrates bitwise operations acting on 4-bit busses for other basic logic functions.
A complete command such as assign y4 = ~(a & b); is called a statement. assign out = in1 op in2; is called a continuous assignment statement.
|
module gates_sv
( input logic [3:0] a, b, output logic [3:0] y1, y2, y3, y4, y5 );
/*five different two-input logic gates acting on 4-bit busses */ assign y1 = a & b; // AND assign y2 = a | b; // OR assign y3 = a ^ b; // XOR assign y4 = ~(a & b); // NAND assign y5 = ~(a |b); // NOR endmodule
|
module gates_v
( input [3:0] a, b, output [3:0] y1, y2, y3, y4, y5 );
/* Five different two-input logic gates acting on 4 bit busses */ assign y1 = a & b; // AND assign y2 = a | b; // OR assign y3 = a ^ b; // XOR assign y4 = ~(a & b); // NAND assign y5 = ~(a | b); // NOR endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity gates_vhd is port ( a, b: in STD_LOGIC_VECTOR(3 downto 0); y1, y2, y3, y4, y5: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth of gates_vhd is begin -- five different two-input logic gates -- acting on 4-bit busses y1 <= a and b; y2 <= a or b; y3 <= a xor b; y4 <= a nand b; y5 <= a nor b; end;
|
HDL Example 4.4 EIGHT-INPUT AND
As one would expect, |, ^, ~&, and ~ | reduction operators are available for OR, XOR, NAND, and NOR as well. Recall that a multi-input XOR performs parity, returning TRUE if an odd number of inputs are TRUE.
|
module and8_sv ( input logic [7:0] a, output logic y, y1 );
assign y = &a; // &a is much easier to write than assign y1 = a[7] & a[6] & a[5] & a[4] & a[3] & a[2] & a[1] & a[0]; endmodule
|
module and8_v ( input [7:0] a, output y ); assign y = &a; // &a is much easier to write than // assign y a[7] & a[6] & a[5] & a[4] & // a[3] & a[2] & a[1] & a[0]; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity and8_vhd is port ( a: in STD_LOGIC_VECTOR(7 downto 0); y: out STD_LOGIC ); end;
architecture synth of and8_vhd is begin y <= a(7) and a(6) and a(5) and a(4) and a(3) and a(2) and a(1) and a(0); end;
|
HDL Example 4.5 2to1 MULTIPLEXER
HDL Example 4.5 illustrates a 2:1 multiplexer using a conditional assignment. Conditional assignments select the output from among alternatives based on an input called the condition.
|
module mux2_sv ( input logic [3:0] d0, d1, input logic s, output logic [3:0] y ); assign y = s ? d1 : d0; endmodule |
module mux2_v ( input [3:0] d0, d1, input s, output [3:0] y ); assign y = s ? d1 : d0; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity mux2_vhd is port ( d0, d1: in STD_LOGIC_VECTOR(3 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end; architecture synth of mux2_vhd is begin y <= d1 when s = '0' else d0; end; |
HDL Example 4.6 4to1 MULTIPLEXER
The multiplexer has multiple data (d) and one-hot enable (e) inputs. When one of the enables is asserted, the associated data is passed to the output.
|
module mux4_sv ( input logic [3:0] d0, d1, d2, d3, input logic [1:0] s, output logic [3:0] y ); assign y = s[1] ? (s[0] ? d3 : d2): (s[0] ? d1 : d0); endmodule
|
module mux4_v ( input [3:0] d0, d1, d2, d3, input [1:0] s, output [3:0] y ); assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0); endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity mux4_vhd is port( d0, d1,d2, d3: in STD_LOGIC_VECTOR(3 downto 0); s: in STD_LOGIC_VECTOR(1 downto 0); y: out STD_LOGIC_VECTOR(3 downto 0)--; --y_1: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth1 of mux4_vhd is begin y <= d0 when s = "00" else d1 when s = "01" else d2 when s = "10" else d3;
-- next code make uncorrect RTL and Synthesis --with s select y_1 <= -- d0 when "00", -- d1 when "01", -- d2 when "10", -- d3 when others; end;
|
HDL Example 4.7 FULL ADDER
P and G are called internal variables, because they are neither inputs nor outputs but are used only internal to the module. They are similar to local variables in programming languages.
|
module fulladder_sv ( input logic a, b, cin, output logic s, cout );
logic p, g;
assign p = a ^ b; assign g = a & b; assign s = p ^ cin; assign cout = g |(p & cin); endmodule
|
module fulladder_v ( input a, b, cin, output s, cout );
wire p, g;
assign p = a ^ b; assign g = a & b; assign s = p ^ cin; assign cout = g | (p & cin); endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity fulladder_vhd is port ( a, b, cin: in STD_LOGIC; s, cout: out STD_LOGIC ); end;
architecture synth of fulladder_vhd is
signal p, g: STD_LOGIC;
begin p <= a xor b; g <= a and b; s <= p xor cin; cout <= g or (p and cin); end;
|
HDL Example 4.10 TRISTATE BUFFER
HDLs use x to indicate an invalid logic level. If a bus is simultaneously driven to 0 and 1 by two enabled tristate buffers (or other gates), the result is x, indicating contention. If all the tristate buffers driving a bus are simultaneously OFF, the bus will float, indicated by z.
|
module tristate_sv ( input logic [3:0] a, input logic en, output tri [3:0] y ); assign y = en ? a : 4'bz; endmodule |
module tristate_v ( input [3:0] a, input en, output [3:0] y ); assign y = en ? a : 4'bz; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity tristate_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); en: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth of tristate_vhd is begin y <= a when en = '1' else "ZZZZ"; --y <= "ZZZZ" when en = '0' else a; end;
|
HDL Example 4.12 BIT SWIZZLING
Often it is necessary to operate on a subset of a bus or to concatenate (join together) signals to form busses. These operations are collectively known as bit swizzling.
|
//HDL Example 4.12 BIT SWIZZLING
module BIT_SWIZZLING_sv ( input logic [4:0] C, input logic [4:0] D, output logic [8:0] Y );
assign Y = {C[2:1], {3{D[0]}}, C[0], 3'b101}; //y = c2c1d0d0d0c0101 3'b101 - constant
endmodule
|
//HDL Example 4.12 BIT SWIZZLING
module BIT_SWIZZLING_v ( input [4:0] C, input [4:0] D, output [8:0] Y );
assign Y = {C[2:1], {3{D[0]}}, C[0], 3'b101}; //y = c2c1d0d0d0c0101 3'b101 - constant
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity BIT_SWIZZLING_vhd is port ( C: in STD_LOGIC_VECTOR(4 downto 0); D: in STD_LOGIC_VECTOR(4 downto 0); Y: out STD_LOGIC_VECTOR(8 downto 0) ); end;
architecture synth of BIT_SWIZZLING_vhd is begin Y <= C(2 downto 1) & D(0) & D(0) & D(0) & C(0) & "101"; end;
|
HDL Example 4.14 STRUCTURAL MODEL OF 4to1 MULTIPLEXER
HDL Example 4.14 shows how to assemble a 4:1 multiplexer from three 2:1 multiplexers. Each copy of the 2:1 multiplexer is called an instance. Multiple instances of the same module are distinguished by distinct names, in this case lowmux, highmux, and finalmux. This is an example of regularity, in which the 2:1 multiplexer is reused many times.
|
module mux4_sv ( input logic [3:0] d0, d1, d2, d3, input logic [1:0] s, output logic [3:0] y );
logic [3:0] low, high;
mux2_sv lowmux(d0, d1, s[0], low); mux2_sv highmux(d2, d3, s[0], high); mux2_sv finalmux(low, high, s[1], y);
endmodule
---------------------------------------------------------
module mux2_sv ( input [3:0] d0, input [3:0] d1, input s, output [3:0] y ); assign y = s ? d1 : d0; endmodule
|
module mux4_v ( input [3:0] d0, d1, d2, d3, input [1:0] s, output [3:0] y );
wire [3:0] low, high;
mux2_v lowmux (d0, d1, s[0], low); mux2_v highmux (d2, d3, s[0], high); mux2_v finalmux (low, high, s[1], y);
endmodule
---------------------------------------------------------
module mux2_v ( input [3:0] d0, input [3:0] d1, input s, output [3:0] y ); assign y = s ? d1 : d0; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity mux4_vhd is port ( d0, d1, d2, d3: in STD_LOGIC_VECTOR (3 downto 0); s: in STD_LOGIC_VECTOR (1 downto 0); y: out STD_LOGIC_VECTOR (3 downto 0) ); end;
architecture struct of mux4_vhd is
component mux2_vhd port ( d0, d1 : in STD_LOGIC_VECTOR (3 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR (3 downto 0) ); end component;
signal low, high: STD_LOGIC_VECTOR (3 downto 0);
begin
lowmux: mux2_vhd port map ( d0 => d0, d1 => d1, s => s(0), y => low ); highmux: mux2_vhd port map (d2, d3, s(0), high); finalmux: mux2_vhd port map (low, high, s(1), y);
end;
---------------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all; entity mux2_vhd is port ( d0: in STD_LOGIC_VECTOR (3 downto 0); d1: in STD_LOGIC_VECTOR (3 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR (3 downto 0) ; end;
architecture synth of mux2_vhd is begin y <= d0 when s = '0' else d1; end;
|
HDL Example 4.15 STRUCTURAL MODEL OF 2to1 MULTIPLEXER
The structural modeling to construct a 2:1 multiplexer from a pair of tristate buffers.
|
module mux2_sv ( input logic [3:0] d0, d1, input logic s, output tri [3:0] y ); tristate_sv t0(d0, ~s, y); tristate_sv t1(d1, s, y); endmodule
---------------------------------------------------------
module tristate_sv ( input logic [3:0] a, input logic en, output tri [3:0] y ); assign y = en ? a : 4'bz; endmodule
|
module mux2_v ( input [3:0] d0, d1, input s, output [3:0] y );
tristate_v t0 (d0, ~s, y); tristate_v t1 (d1, s, y); endmodule
---------------------------------------------------------
module tristate_v ( input [3:0] a, input en, output [3:0] y ); assign y = en ? a : 4'bz; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mux2_vhd is port ( d0, d1: in STD_LOGIC_VECTOR(3 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture struct of mux2_vhd is
component tristate_vhd port ( a: in STD_LOGIC_VECTOR(3 downto 0); en: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end component;
signal sbar: STD_LOGIC;
begin
sbar <= not s; t0: tristate_vhd port map(d0, sbar, y); t1: tristate_vhd port map(d1, s, y); end;
---------------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all; entity tristate_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); en: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end; architecture synth of tristate_vhd is begin y <= a when en = '1' else "ZZZZ"; --y <= "ZZZZ" when en = '0' else a; end;
|
HDL Example 4.16 ACCESSING PARTS OF BUSSES
shows how modules can access part of a bus. An 8-bit wide 2:1 multiplexer is built using two of the 4-bit 2:1 multiplexers already defined, operating on the low and high nibbles of the byte. In general, complex systems are designed hierarchically. The overall system is described structurally by instantiating its major components. Each of these components is described structurally from its building blocks, and so forth recursively until the pieces are simple enough to describe behaviorally. It is good style to avoid (or at least to minimize) mixing structural and behavioral descriptions within a single module.
|
module mux2_8_sv ( input logic [7:0] d0, d1, input logic s, output logic [7:0] y );
mux2_sv lsbmux(d0[3:0], d1[3:0], s, y[3:0]); mux2_sv msbmux(d0[7:4], d1[7:4], s, y[7:4]);
endmodule
|
module mux2_8_v ( input [7:0] d0, d1, input s, output [7:0] y );
mux2_v lsbmux (d0[3:0], d1[3:0], s, y[3:0]); mux2_v msbmux (d0[7:4], d1[7:4], s, y[7:4]);
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity mux2_8_vhd is port ( d0, d1: in STD_LOGIC_VECTOR(7 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR(7 downto 0) ); end;
architecture struct of mux2_8_vhd is
component mux2_vhd port ( d0, d1: in STD_LOGIC_VECTOR(3 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR(3 downto 0) ); end component;
begin
lsbmux: mux2_vhd port map ( d0 => d0(3 downto 0), d1 => d1(3 downto 0), s => s, y => y(3 downto 0) );
msbmux: mux2_vhd port map ( d0 => d0(7 downto 4), d1 => d1(7 downto 4), s => s, y => y(7 downto 4) );
end;
|
HDL Example 4.17 REGISTER
The flip-flop includes only clk in the sensitive list. It remembers its old value of q until the next rising edge of the clk, even if d changes in the interim. In contrast, Verilog continuous assignment statements (assign) and VHDL concurrent assignment statements (<=) are reevaluated any time any of the inputs on the right-hand side changes. Therefore, such code necessarily describes combinational logic.
|
module flop_sv ( input logic clk, input logic [3:0] d, output logic [3:0] q );
always_ff @(posedge clk) q <= d;
endmodule
|
module flop_v ( input clk, input [3:0] d, output reg [3:0] q );
always @ (posedge clk) q <= d;
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity flop_vhd is port ( clk: in STD_LOGIC; d: in STD_LOGIC_VECTOR(3 downto 0); q: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth of flop_vhd is
begin process(clk) begin if rising_edge(clk) then -- if clk'event and clk = '1' then q <= d; end if; end process;
end;
|
HDL Example 4.18 RESETTABLE REGISTER
Generally, it is good practice to use resettable registers so that on powerup you can put your system in a known state. The reset may be either asynchronous or synchronous. Recall that asynchronous reset occurs immediately, whereas synchronous reset clears the output only on the next rising edge of the clock.
|
module flop_ar_sv ( input logic clk, input logic reset, input logic [3:0] d, output logic [3:0] q ); // asynchronous reset
always_ff @(posedge clk, posedge reset) if (reset) q <= 4'b0; else q <= d; endmodule
---------------------------------------------------------
module flopr_sr_sv ( input logic clk, input logic reset, input logic [3:0] d, output logic [3:0] q ); // synchronous reset always_ff @(posedge clk) if (reset) q <= 4'b0; else q <= d; endmodule
|
module flop_ar_v ( input clk, input reset, input [3:0] d, output reg [3:0] q ); // asynchronous reset
always @ (posedge clk, posedge reset) if (reset) q <= 4'b0; else q <= d; endmodule
---------------------------------------------------------
module flopr_sr_v ( input clk, input reset, input [3:0] d, output reg [3:0] q ); // synchronous reset always @ (posedge clk) if (reset) q <= 4'b0; else q <= d; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity flopr_as_vhd is
port ( clk, reset: in STD_LOGIC; d: in STD_LOGIC_VECTOR(3 downto 0); q: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture asynchronous of flopr_as_vhd is
begin
process(clk, reset) begin if reset = '1' then q <= "0000"; elsif rising_edge(clk) then q <= d; end if; end process; end;
---------------------------------------------------------
library IEEE; use IEEE.STD_LOGIC_1164.all; entity flopr_sr_vhd is
port ( clk, reset: in STD_LOGIC; d: in STD_LOGIC_VECTOR(3 downto 0); q: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synchronous of flopr_sr_vhd is
begin
process(clk) begin if rising_edge(clk) then if reset = '1' then q <= "0000"; else q <= d; end if; end if; end process; end;
|
HDL Example 4.19 RESETTABLE ENABLED REGISTER
Enabled registers respond to the clock only when the enable is asserted. It is retains its old value if both reset and en are FALSE.
|
module flopenr_sv ( input logic clk, input logic reset, input logic en, input logic [3:0] d, output logic [3:0] q ); // asynchronous reset always_ff @(posedge clk, posedge reset) if (reset) q <= 4'b0; else if (en) q <= d; endmodule
|
module flopenr_v ( input clk, input reset, input en, input [3:0] d, output reg[3:0] q ); // asynchronous reset always @(posedge clk, posedge reset) if (reset) q <= 4'b0; else if (en) q <= d; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity flopenr_vhd is port ( clk, reset, en: in STD_LOGIC; d: in STD_LOGIC_VECTOR(3 downto 0); q: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture asynchronous of flopenr_vhd is -- asynchronous reset begin process(clk, reset) begin if reset = '1' then q <= "0000"; elsif rising_edge(clk) then if en ='1' then q <= d; end if; end if; end process; end;
|
HDL Example 4.20 SYNCHRONIZER
A single always/process statement can be used to describe multiple pieces of hardware. For example, consider the synchronizer made of two back-to-back flip-flops. On the rising edge of clk, d is copied to n1. At the same time, n1 is copied to q.
|
module sync_sv ( input logic clk, input logic d, output logic q ); logic n1; always_ff @(posedge clk) begin n1 <= d; // nonblocking q <= n1; // nonblocking end endmodule
|
module sync_v ( input clk, input d, output reg q );
reg n1;
always @ (posedge clk) begin n1 <= d; q <= n1; end endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; library IEEE; use IEEE.STD_LOGIC_1164.all; entity sync_vhd is port ( clk: in STD_LOGIC; d: in STD_LOGIC; q: out STD_LOGIC ); end; architecture good of sync_vhd is signal n1: STD_LOGIC; begin process(clk) begin if rising_edge(clk) then n1 <= d; q <= n1; end if; end process; end; |
HDL Example 4.21 Latches Do not do that
A D latch is transparent when the clock is HIGH, allowing data to flow from input to output. The latch becomes opaque when the clock is LOW, retaining its old state. HDL Example 4.22 shows the idiom for a D latch. Not all synthesis tools support latches well. Unless you know that your tool does support latches and you have a good reason to use them, avoid them, and use edge-triggered flip-flops instead. Furthermore, take care that your HDL does not imply any unintended latches, something that is easy to do if you aren’t attentive. Many synthesis tools warn you when a latch is created; if you didn’t expect one, track down the bug in your HDL
|
module latch_sv ( input logic clk, input logic [3:0] d, output logic [3:0] q );
always_latch // it is similar to always @(clk, d) if (clk) q <= d; endmodule
|
module latch_v ( input clk, input [3:0] d, output reg [3:0] q );
always @ (clk, d) if (clk) q <= d; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity latch_vhd is port ( clk: in STD_LOGIC; d: in STD_LOGIC_VECTOR(3 downto 0); q: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture synth of latch_vhd is begin process(clk, d) begin if clk = '1' then q <= d; end if; end process; end;
|
HDL Example 4.22 INVERTER USING always_process
However, always/process statements can also be used to describe combinational logic behaviorally if the sensitivity list is written to respond to changes in all of the inputs and the body prescribes the output value for every possible input combination. HDL Example 4.22 uses always/process statements to describe a bank of four inverters.
The example is poor applications of always/process statements for modeling combinational logic because they require more lines than the equivalent approach with assignment statements. Moreover, they pose the risk of inadvertently implying sequential logic if the inputs are left out of the sensitivity list. However, case and if statements are convenient for modeling more complicated combinational logic. case and if statements must appear within always/process statements and are examined in the next sections.
|
module inv_sv ( input logic [3:0] a, output logic[3:0] y );
always_comb y = ~a; endmodule
|
module inv_v ( input [3:0] a, output reg [3:0] y );
always @ (*) y = ~a;
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity inv_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture proc of inv_vhd is
begin --process(all) begin -- supported in VHDL 1076-2008 process (a) begin y <= not a; end process; end;
|
HDL Example 4.23 FULL ADDER USING always_process
Full adder using intermediate signals p and g to compute s and cout. It produces the same circuit from Figure 4.8, but uses always/process statements in place of assignment statements.
The example is poor applications of always/process statements for modeling combinational logic because they require more lines than the equivalent approach with assignment statements. Moreover, they pose the risk of inadvertently implying sequential logic if the inputs are left out of the sensitivity list. However, case and if statements are convenient for modeling more complicated combinational logic. case and if statements must appear within always/process statements and are examined in the next sections.
|
module fulladder_sv ( input logic a, b, cin, output logic s, cout );
logic p, g;
always_comb begin p = a ^ b; // blocking g = a & b; // blocking s = p ^ cin; // blocking cout = g |(p & cin); // blocking end endmodule
|
module fulladder_v ( input a, b, cin, output reg s, cout ); reg p, g; always @ (*) begin p = a ^ b;// blocking g = a & b;// blocking s = p ^ cin;// blocking cout = g | (p & cin);// blocking end endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity fulladder_vhd is
port ( a, b, cin: in STD_LOGIC; s, cout: out STD_LOGIC ); end;
architecture synth of fulladder_vhd is begin process(all) -- supported in VHDL 1076-2008 --process (a, b, cin) variable p, g: STD_LOGIC; begin p := a xor b; -- blocking g := a and b; -- blocking s <= p xor cin; cout <= g or (p and cin); end process; end;
|
HDL Example 4.24 SEVEN-SEGMENT DISPLAY DECODER
A better application of using the always/process statement for combinational logic is a seven-segment display decoder that takes advantage of the case statement that must appear inside an always/process statement. The case statement performs different actions depending on the value of its input. A case statement implies combinational logic if all possible input combinations are defined; otherwise, it implies sequential logic, because the output will keep its old value in the undefined cases.
|
module sevenseg_sv ( input logic [3:0] data, output logic [6:0] segments );
always_comb case(data) // abc_defg 0: segments = 7'b111_1110; 1: segments = 7'b011_0000; 2: segments = 7'b110_1101; 3: segments = 7'b111_1001; 4: segments = 7'b011_0011; 5: segments = 7'b101_1011; 6: segments = 7'b101_1111; 7: segments = 7'b111_0000; 8: segments = 7'b111_1111; 9: segments = 7'b111_0011; default: segments = 7'b000_0000; endcase endmodule
|
module sevenseg_v ( input [3:0] data, output reg [6:0] segments );
always @ (*) case (data) // abc_defg 0: segments = 7'b111_1110; 1: segments = 7'b011_0000; 2: segments = 7'b110_1101; 3: segments = 7'b111_1001; 4: segments = 7'b011_0011; 5: segments = 7'b101_1011; 6: segments = 7'b101_1111; 7: segments = 7'b111_0000; 8: segments = 7'b111_1111; 9: segments = 7'b111_1011; default: segments = 7'b000_0000; endcase endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity sevenseg_vhd is port ( data: in STD_LOGIC_VECTOR(3 downto 0); segments: out STD_LOGIC_VECTOR(6 downto 0) ); end;
architecture synth of sevenseg_vhd is begin process(all) begin --(VHDL 2008) case data is -- abcdefg when X"0" => segments <= "1111110"; when X"1" => segments <= "0110000"; when X"2" => segments <= "1101101"; when X"3" => segments <= "1111001"; when X"4" => segments <= "0110011"; when X"5" => segments <= "1011011"; when X"6" => segments <= "1011111"; when X"7" => segments <= "1110000"; when X"8" => segments <= "1111111"; when X"9" => segments <= "1110011"; when others => segments <= "0000000"; end case; end process; end;
|
HDL Example 4.25 3to8 DECODER
Ordinary decoders are also commonly written with case statements.
|
module decoder3_8_sv ( input logic [2:0] a, output logic [7:0] y ); always_comb case(a) 3'b000: y = 8'b00000001; 3'b001: y = 8'b00000010; 3'b010: y = 8'b00000100; 3'b011: y = 8'b00001000; 3'b100: y = 8'b00010000; 3'b101: y = 8'b00100000; 3'b110: y = 8'b01000000; 3'b111: y = 8'b10000000; default: y = 8'bxxxxxxxx; endcase endmodule
|
module decoder3_8_v ( input [2:0] a, output reg [7:0] y );
always @ (*) case (a) 3'b000: y = 8'b00000001; 3'b001: y = 8'b00000010; 3'b010: y = 8'b00000100; 3'b011: y = 8'b00001000; 3'b100: y = 8'b00010000; 3'b101: y = 8'b00100000; 3'b110: y = 8'b01000000; 3'b111: y = 8'b10000000; default: y = 8'bxxxxxxxx; endcase endmodule
|
module decoder3_8_svmodule decoder3_8_sv ( input logic [2:0] a, output logic [7:0] y ); always_comb case(a) 3'b000: y = 8'b00000001; 3'b001: y = 8'b00000010; 3'b010: y = 8'b00000100; 3'b011: y = 8'b00001000; 3'b100: y = 8'b00010000; 3'b101: y = 8'b00100000; 3'b110: y = 8'b01000000; 3'b111: y = 8'b10000000; default: y = 8'bxxxxxxxx; end case end module
|
HDL Example 4.26 PRIORITY CIRCUIT
|
module priority_sv ( input logic [3:0] a, output logic [3:0] y ); always_comb if(a[3])y <= 4'b1000; else if (a[2])y <= 4'b0100; else if (a[1])y <= 4'b0010; else if (a[0])y <= 4'b0001; else y <= 4'b0000; endmodule
|
module priority_v ( input [3:0] a, output reg [3:0] y ); always @ (*) if (a[3]) y = 4'b1000; else if (a[2]) y = 4'b0100; else if (a[1]) y = 4'b0010; else if (a[0]) y = 4'b0001; else y = 4'b0000; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity priority_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(3 downto 0) ); end; architecture synth of priority_vhd is begin --process(all) begin -- VHDL 2008, but --The Condition Operator is not supported yet for simulation (Vivado 2019.1.1) --process (a) begin --if a(3) then y <= "1000"; --elsif a(2) then y <= "0100"; --elsif a(1) then y <= "0010"; --elsif a(0) then y <= "0001"; --else y <= "0000"; --end if; process (a) begin if a(3) = '1' then y <= "1000"; elsif a(2) = '1' then y <= "0100"; elsif a(1) = '1' then y <= "0010"; elsif a(0) = '1' then y <= "0001"; elsey <= "0000"; end if; end process; end; |
HDL Example 4.27 PRIORITY CIRCUIT USING casez
Verilog also provides the casez statement to describe truth tables with don’t cares (indicated with ? in the casez statement).
|
module priority_casez_sv ( input logic [3:0] a, output logic [3:0] y ); always_comb casez(a) 4'b1??? : y <= 4'b1000; 4'b01?? : y <= 4'b0100; 4'b001? : y <= 4'b0010; 4'b0001 : y <= 4'b0001; default : y <= 4'b0000; endcase endmodule |
module priority_casez_v ( input [3:0] a, output reg [3:0] y );
always @ (*) casez (a) 4'b1???: y = 4'b1000; 4'b01??: y = 4'b0100; 4'b001?: y = 4'b0010; 4'b0001: y = 4'b0001; default: y = 4'b0000; endcase endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity priority_casez_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(3 downto 0) ); end;
architecture dontcare of priority_casez_vhd is
begin process(all) begin --casez a is -- Wrong syntacs --case a is -- wrong design case? a is -- VHDL 2008 Passed the synthesis, implementation, but not supported in Xilinx simulation tools --ERROR: [XSIM 43-4187] File "C:/Zynq_Book/VHDL_SV_Verilog/HDL Example 4.27 PRIORITY CIRCUIT USING casez/HDL Example 4_27 PRIORITY CIRCUIT USING casez.srcs/sources_1/imports/HDL Example 4.27 PRIORITY CIRCUIT USING casez/priority_casez.vhd" Line 16 : The "Vhdl 2008 Matching Case Statement" is not supported yet for simulation. when "1---" => y <= "1000"; when "01--" => y <= "0100"; when "001-" => y <= "0010"; when "0001" => y <= "0001"; when others => y <= "0000"; --end casez; --end case; end case?; end process; end;
|
HDL Example 4.28 FULL ADDER USING NONBLOCKING ASSIGNMENTS not recommended use the nonblocking assigment into combination logic
|
// nonblocking assignments (not recommended) module fulladder_nb_sv ( input logic a, b, cin, output logic s, cout );
logic p, g;
always_comb begin p <= a ^ b; // nonblocking g <= a & b; // nonblocking s <= p ^ cin; cout <= g | (p & cin); end endmodule
|
// nonblocking assignments (not recommended) module fulladder_nb_v ( input a, b, cin, output reg s, cout );
//Because p and g appear on the left hand side of an assignment in an always statement, they must be declared to be reg. reg p, g;
always @ (*) begin p <= a ^ b; // nonblocking g <= a & b; // nonblocking
s <= p ^ cin; cout <= g | (p & cin); end endmodule
|
-- nonblocking assignments (not recommended) library IEEE; use IEEE.STD_LOGIC_1164.all; entity fulladder_nb_vhd is port ( a, b, cin: in STD_LOGIC; s, cout: out STD_LOGIC ); end;
architecture nonblocking of fulladder_nb_vhd is
signal p, g: STD_LOGIC;
begin -- process (a, b, cin, p, g) begin VHDL process(all) begin -- VHDL 2008 p <= a xor b; -- nonblocking g <= a and b; -- nonblocking s <= p xor cin; cout <= g or (p and cin); end process;
end;
|
HDL Example 4.29 BAD SYNC W B_ASS Dont make
Because n1 is invisible to the outside world and does not influence the behavior of q, the synthesizer optimizes it away entirely
|
// Bad implementation of a synchronizer using blocking // assignments module syncbad_sv ( input logic clk, input logic d, output logic q );
logic n1;
always_ff @(posedge clk)
begin n1 = d; // blocking q = n1; // blocking end
endmodule
|
// Bad implementation using blocking assignments module syncbad_v ( input clk, input d, output reg q );
reg n1;
always @ (posedge clk) begin n1 = d; // blocking q = n1; // blocking end endmodule
|
-- Bad implementation of a synchronizer using blocking –– assignment library IEEE; use IEEE.STD_LOGIC_1164.all; entity syncbad_vhd is port ( clk: in STD_LOGIC; d: in STD_LOGIC; q: out STD_LOGIC ); end;
architecture bad of syncbad_vhd is begin
process(clk) variable n1: STD_LOGIC; begin if rising_edge(clk) then n1 := d; -- blocking q <= n1; end if; end process;
end;
|
HDL Example 4.30 DIVIDE-BY-3 FINITE STATE MACHINE
Recall that a finite state machine (FSM) consists of a state register and two blocks of combinational logic to compute the next state and the output given the current state and the input
It provides an asynchronous reset to initialize the FSM. The state register uses the ordinary idiom for flip-flops. The next state and output logic blocks are combinational.
|
module divideby3FSM_sv ( input logic clk, input logic reset, output logic y );
typedef enum logic [1:0] {S0, S1, S2} statetype; statetype [1:0] state, nextstate;
// state register
always_ff @(posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always_comb case (state) S0: nextstate <= S1; S1: nextstate <= S2; S2: nextstate <= S0; default: nextstate <= S0; endcase // output logic assign y = (state == S0);
endmodule
|
module divideby3FSM_v ( input clk, input reset, output y );
reg [1:0] state, nextstate;
parameter S0 = 2'b00; parameter S1 = 2'b01; parameter S2 = 2'b10;
// state register always @ (posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always @ (*) case (state) S0: nextstate = S1; S1: nextstate = S2; S2: nextstate = S0; default: nextstate = S0; endcase // output logic assign y = (state == S0);
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all; entity divideby3FSM_vhd is port ( reset : in STD_LOGIC; clk : in STD_LOGIC; y : out STD_LOGIC ); end;
architecture synth of divideby3FSM_vhd is type statetype is (S0, S1, S2); signal state, nextstate: statetype;
begin -- state register process(clk, reset) begin --if reset then -- VHDL 2008 [XSIM 43-4187] HDL Example 4.30 DIVIDE-BY-3 FINITE STATE MACHINE/divideby3FSM.vhd" Line 19 : The "Vhdl 2008 Condition Operator" is not supported yet for simulation. if reset = '1' then -- VHDL state <= S0; elsif rising_edge(clk) then state <= nextstate; end if; end process;
-- next state logic nextstate <= S1 when state = S0 else S2 when state = S1 else S0;
-- output logic y <= '1' when state = S0 else '0';
end;
|
HDL Example 4.31 PATTERN RECOGNIZER MOORE FSM
The next two examples describe the snail pattern recognizer FSM The code shows how to use case and if statements to handle next state and output logic that depend on the inputs as well as the current state. In the Moore machine, the output depends only on the current state
|
//The daughter snail smiles whenever she slides over the pattern 1101. module patternMoore_sv ( input logic clk, input logic reset, input logic a, output logic y );
typedef enum logic [2:0] {S0, S1, S2, S3, S4} statetype; statetype state, nextstate;
// state register always_ff @(posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always_comb case (state) S0: if (a) nextstate = S1; else nextstate = S0; S1: if (a) nextstate = S2; else nextstate = S0; S2: if (a) nextstate = S2; else nextstate = S3; S3: if (a) nextstate = S4; else nextstate = S0; S4: if (a) nextstate = S2; else nextstate = S0; default: nextstate = S0; endcase
// output logic assign y = (state == S4);
endmodule
|
//The daughter snail smiles whenever she slides over the pattern 1101. module patternMoore_v ( input clk, input reset, input a, output y );
reg [2:0] state, nextstate; parameter S0 = 3'b000; parameter S1 = 3'b001; parameter S2 = 3'b010; parameter S3 = 3'b011; parameter S4 = 3'b100;
// state register always @ (posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always @ (*) case (state) S0: if (a) nextstate = S1; else nextstate = S0; S1: if (a) nextstate = S2; else nextstate = S0; S2: if (a) nextstate = S2; else nextstate = S3; S3: if (a) nextstate = S4; else nextstate = S0; S4: if (a) nextstate = S2; else nextstate = S0; default: nextstate = S0; endcase
// output logic assign y = (state == S4);
endmodule
|
-- The daughter snail smiles whenever she slides over the pattern 1101 or the pattern 1110. library IEEE; use IEEE.STD_LOGIC_1164.all; entity patternMoore_vhd is port ( reset : in STD_LOGIC; clk : in STD_LOGIC; a : in STD_LOGIC; y : out STD_LOGIC ); end;
architecture synth of patternMoore_vhd is type statetype is (S0, S1, S2, S3, S4); signal state, nextstate: statetype;
begin -- state register process (clk, reset) begin if reset = '1' then state <= S0; elsif clk'event and clk = '1' then state <= nextstate; end if; end process;
-- next state logic process (state, a) begin -- process(all) begin case state is when S0 => if a = '1' then nextstate <= S1; else nextstate <= S0; end if; when S1 => if a = '1' then nextstate <= S2; else nextstate <= S0; end if; when S2 => if a = '1' then nextstate <= S2; else nextstate <= S3; end if; when S3 => if a = '1' then nextstate <= S4; else nextstate <= S0; end if; when S4 => if a = '1' then nextstate <= S2; else nextstate <= S0; end if; when others => nextstate <= S0; end case; end process;
-- output logic y <= '1' when state = S4 else '0'; end;
|
HDL Example 4.32 PATTERN RECOGNIZER MEALY FSM
The next two examples describe the snail pattern recognizer FSM. The code shows how to use case and if statements to handle next state and output logic that depend on the inputs as well as the current state. In the Mealy machine, the output logic depends on both the current state and inputs.
|
//The daughter snail smiles whenever she slides over the pattern 1101. module patternMealy_sv ( input logic clk, input logic reset, input logic a, output logic y );
typedef enum logic [1:0] {S0, S1, S2, S3} statetype; statetype state, nextstate;
// state register always_ff @(posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always_comb case (state) S0: if (a) nextstate = S1; else nextstate = S0; S1: if (a) nextstate = S2; else nextstate = S0; S2: if (a) nextstate = S2; else nextstate = S3; S3: if (a) nextstate = S1; else nextstate = S0; default: nextstate = S0; endcase
// output logic assign y = (a & state == S3);
endmodule
|
//The daughter snail smiles whenever she slides over the pattern 1101. module patternMealy_v ( input clk, input reset, input a, output y );
reg [1:0] state, nextstate; parameter S0 = 2'b00; parameter S1 = 2'b01; parameter S2 = 2'b10; parameter S3 = 2'b11;
// state register always @ (posedge clk, posedge reset) if (reset) state <= S0; else state <= nextstate;
// next state logic always @ (*) case (state) S0: if (a) nextstate = S1; else nextstate = S0; S1: if (a) nextstate = S2; else nextstate = S0; S2: if (a) nextstate = S2; else nextstate = S3; S3: if (a) nextstate = S1; else nextstate = S0; default: nextstate = S0; endcase
// output logic assign y = (a & state == S3);
endmodule
|
--The daughter snail smiles whenever she slides over the pattern 1101. library IEEE; use IEEE.STD_LOGIC_1164.all;
entity patternMealy_vhd isport ( reset : in STD_LOGIC; clk : in STD_LOGIC; a : in STD_LOGIC; y : out STD_LOGIC ); end;
architecture synth of patternMealy_vhd is type statetype is (S0, S1, S2, S3); signal state, nextstate: statetype; begin -- state register process (clk, reset) begin if reset = '1' then state <= S0; elsif clk'event and clk = '1' then state <= nextstate; end if; end process;
-- next state logic process(state, a) begin case state is when S0 => if a = '1' then nextstate <= S1; else nextstate <= S0; end if; when S1 => if a = '1' then nextstate <= S2; else nextstate <= S0; end if; when S2 => if a = '1' then nextstate <= S2; else nextstate <= S3; end if; when S3 => if a = '1' then nextstate <= S1; else nextstate <= S0; end if; when others => nextstate <= S0; end case; end process;
|
HDL Example 4.33a unsigned multiplier
|
// 4.33(a): unsigned multiplier module multiplier_sv ( input logic [3:0] a, b, output logic [7:0] y );
assign y = a * b; endmodule
// 5.4(): unsigned multiplier //module multiplier #(parameter N = 8) //(input logic [N–1:0] a, b, //output logic [2*N–1:0] y); //assign y = a * b; //endmodule
|
// 4.33(a): unsigned multiplier module multiplier_v ( input [3:0] a, b, output [7:0] y ); assign y = a * b; endmodule
//HDL Example 5.4 MULTIPLIER //module multiplier # (parameter N 8) //(input [N-1:0] a, b, //output [2*N-1:0] y); //assign y a * b; //endmodule
|
-- 4.33(a): unsigned multiplier
library IEEE; use IEEE.STD_LOGIC_1164.all; --use IEEE.NUMERIC_STD_UNSIGNED.all; -- VHDL2008 (but not always work) use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity multiplier_vhd is port ( a: in STD_LOGIC_VECTOR(3 downto 0); b: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(7 downto 0) ); end;
architecture synth of multiplier_vhd is begin y <= a * b; end;
--library IEEE; use IEEE.STD_LOGIC_1164.ALL; --use IEEE.STD_LOGIC_UNSIGNED.ALL; --entity multiplier is --generic (N: integer : 8); --port (a, b: in STD_LOGIC_VECTOR(N-1 downto 0); --y: out STD_LOGIC_VECTOR(2*N-1 downto 0)); --end; --architecture synth of multiplier is --begin --y <= a * b; --end;
|
HDL Example 4.33b signed multiplier
|
// 4.33(b): signed multiplier module multiplier_sv ( input logic signed [3:0] a, input logic signed [3:0] b, output logic signed [7:0] y ); assign y = a * b; endmodule |
// 4.33(b): signed multiplier module multiplier_v ( input signed [3:0] a, input signed [3:0] b, output signed [7:0] y );
assign y = a * b; endmodule
|
--4.33(b): signed multiplier
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; use IEEE.STD_LOGIC_SIGNED.ALL; --use ieee.std_logic_arith.all ; --Use numeric_std or std_logic_arith, but never both
entity multiplier_vhd is port ( -- a: in SIGNED STD_LOGIC_VECTOR(3 downto 0); -- b: in SIGNED STD_LOGIC_VECTOR(3 downto 0); -- y: out SIGNED STD_LOGIC_VECTOR(7 downto 0) a: in STD_LOGIC_VECTOR(3 downto 0); b: in STD_LOGIC_VECTOR(3 downto 0); y: out STD_LOGIC_VECTOR(7 downto 0) ); end;
architecture synth of multiplier_vhd is
signal a_signed : signed(3 downto 0); signal b_signed : signed(3 downto 0); signal y_signed : signed(7 downto 0);
begin a_signed <= signed(a); b_signed <= signed(b); y <= a * b; y <= std_logic_vector(y_signed);
end;
|
HDL Example 4.34a PARAMETERIZED N-BIT MULTIPLEXERS
|
module mux4_8_sv ( input logic [7:0] d0, input logic [7:0] d1, input logic [7:0] d2, input logic [7:0] d3, input logic [1:0] s, output logic [7:0] y );
logic [7:0] low, hi;
mux2_sv lowmux(d0, d1, s[0], low); mux2_sv himux(d2, d3, s[0], hi); mux2_sv outmux(low, hi, s[1], y);
endmodule
|
module mux4_8_v ( input [7:0] d0, input [7:0] d1, input [7:0] d2, input [7:0] d3, input [1:0] s, output [7:0] y );
wire [7:0] low, hi;
mux2_v lowmux (d0, d1, s[0], low); mux2_v himux (d2, d3, s[0], hi); mux2_v outmux (low, hi, s[1], y);
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity mux4_8_vhd is port ( d0: in STD_LOGIC_VECTOR(7 downto 0); d1: in STD_LOGIC_VECTOR(7 downto 0); d2: in STD_LOGIC_VECTOR(7 downto 0); d3: in STD_LOGIC_VECTOR(7 downto 0); s: in STD_LOGIC_VECTOR(1 downto 0); y: out STD_LOGIC_VECTOR(7 downto 0) ); end;
architecture struct of mux4_8_vhd is
component mux2_vhd generic(width: integer := 8); port( d0: in STD_LOGIC_VECTOR(width-1 downto 0); d1: in STD_LOGIC_VECTOR(width-1 downto 0); s: in STD_LOGIC; y: out STD_LOGIC_VECTOR(width-1 downto 0) ); end component;
signal low, hi: STD_LOGIC_VECTOR(7 downto 0);
begin lowmux: mux2_vhd port map(d0, d1, s(0), low); himux: mux2_vhd port map(d2, d3, s(0), hi); outmux: mux2_vhd port map(low, hi, s(1), y); end;
|
HDL Example 4.35 PARAMETERIZED Nto2N DECODER
|
module decoder_sv #(parameter N = 3) ( input logic [N - 1:0] a, output logic [2**N - 1:0] y );
always_comb begin y = 0; y[a] = 1; end endmodule
|
module decoder_v #(parameter N = 3) ( input [N - 1:0] a, output reg [2**N - 1:0] y );
always @ (*) begin y = 0; y[a] = 1; end endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
use IEEE. NUMERIC_STD_UNSIGNED.all;
entity decoder_vhd is generic(N: integer := 3); port ( a: in STD_LOGIC_VECTOR(N - 1 downto 0); y: out STD_LOGIC_VECTOR(2**N - 1 downto 0) ); end;
architecture synth of decoder_vhd is
begin --process(all)-- VHDL 2008 process(a) begin y <= (OTHERS => '0'); y(TO_INTEGER(a)) <= '1'; end process; end;
|
HDL Example 4.36 PARAMETERIZED N-INPUT AND GATE
|
module andN_sv #(parameter width = 8) ( input logic [width - 1:0] a, output logic y );
genvar i; logic [width - 1:0] x;
generate assign x[0] = a[0]; for(i=1; i<width; i=i+1) begin: forloop assign x[i] = a[i] & x[i - 1]; end endgenerate assign y = x[width - 1]; endmodule
|
module andN_v
# (parameter width = 8) ( input [width-1:0] a, output y );
genvar i; wire [width-1 : 1] x;
generate for (i=1; i<width; i=i+1) begin:forloop if (i == 1) assign x[1] = a[0] & a[1]; else assign x[i] = a[i] & x[i-1]; end endgenerate
assign y = x[width-1]; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.all;
entity andN_vhd is generic(width: integer := 8); port ( a: in STD_LOGIC_VECTOR(width - 1 downto 0); y: out STD_LOGIC ); end;
architecture synth of andN_vhd is
signal x: STD_LOGIC_VECTOR(width - 1 downto 0);
begin
x(0) <= a(0);
gen: for i in 1 to width-1 generate x(i) <= a(i) and x(i-1); end generate;
y <= x(width - 1);
end;
--architecture synth of andN is --signal i: integer; --signal x: STD_LOGIC_VECTOR (width - 1 downto 1); --begin --AllBits: for i in 1 to width-1 generate --LowBit: if i = 1 generate --A1: x(1) <= a(0) and a(1); --end generate;
--OtherBits: if i /= 1 generate --Ai: x(i) <= a(i) and x(i-1); --end generate; --end generate;
--y <= x(width-1);
--end;
|
HDL Example 5.1 ADDER |
module adder #(parameter N = 8) ( input logic [N–1:0] a, b, input logic cin, output logic [N–1:0] s, output logic cout ); assign {cout, s} = a + b + cin; endmodule |
module adder #(parameter N 8) ( input [N-1:0] a, b, input cin, output [N-1:0] s, output cout );
assign {cout, s} = a + b + cin; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity adder is generic (N: integer : 8); port ( a, b: in STD_LOGIC_VECTOR(N-1 downto 0); cin: in STD_LOGIC; s: out STD_LOGIC_VECTOR(N-1 downto 0); cout: out STD_LOGIC ); end;
architecture synth of adder is
signal result: STD_LOGIC_VECTOR(N downto 0);
begin result <= (“0” & a) + (“0” & b) + cin; s <= result (N-1 downto 0); cout <= result (N); end;
|
HDL Example 5.2 SUBTRACTOR |
module subtractor #(parameter N = 8) ( input logic [N–1:0] a, b, output logic [N–1:0] y ); assign y = a − b; endmodule |
module subtractor #(parameter N = 8) ( input [N–1:0] a, b, output [N–1:0] y ); assign y = a − b; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD_UNSIGNED.ALL;
entity subtractor is generic(N: integer := 8); port ( a, b: in STD_LOGIC_VECTOR(N–1 downto 0); y: out STD_LOGIC_VECTOR(N–1 downto 0) ); end;
architecture synth of subtractor is begin y <= a – b; end;
|
HDL Example 5.3 COMPARATORS |
module comparator #(parameter N = 8) ( input logic [N–1:0] a, b, output logic eq, neq, lt, lte, gt, gte ); assign eq = (a == b); assign neq = (a != b); assign lt = (a <b); assign lte = (a <= b); assign gt = (a >b); assign gte = (a >= b); endmodule |
module comparator #(parameter N = 8) ( input [N–1:0] a, b, output eq, neq, lt, lte, gt, gte ); assign eq = (a == b); assign neq = (a != b); assign lt = (a <b); assign lte = (a <= b); assign gt = (a >b); assign gte = (a >= b); endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity comparators is generic(N: integer : = 8); port ( a, b: in STD_LOGIC_VECTOR(N–1 downto 0); eq, neq, lt, lte, gt, gte: out STD_LOGIC ); end; architecture synth of comparator is begin eq <= '1' when (a = b) else '0'; neq <= '1' when (a /= b) else '0'; lt <= '1' when (a < b) else '0'; lte <= '1' when (a <= b) else '0'; gt <= '1' when (a > b) else '0'; gte <= '1' when (a >= b) else '0'; end; |
HDL Example 5.4 MULTIPLIER |
module multiplier #(parameter N = 8) (input logic [N–1:0] a, b, output logic [2*N–1:0] y); assign y = a * b; endmodule |
module multiplier #(parameter N = 8) (input [N-1:0] a, b, output [2*N-1:0] y); assign y = a * b; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD_UNSIGNED.ALL; entity multiplier is generic(N: integer := 8); port ( a, b: in STD_LOGIC_VECTOR(N–1 downto 0); y: out STD_LOGIC_VECTOR(2*N–1 downto 0) ); end;
architecture synth of multiplier is begin y <= a * b; end;
|
HDL Example 5.5 COUNTER |
module counter #(parameter N = 8) ( input logic clk, input logic reset, output logic [N–1:0] q ); always_ff @(posedge clk, posedge reset) if (reset)q <= 0; else q <= q + 1; endmodule |
module counter #(parameter N = 8) ( input clk, input reset, output reg [N–1:0] q ); always @(posedge clk, posedge reset) if (reset)q <= 0; else q <= q + 1; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD_UNSIGNED.ALL; entity counter is generic(N: integer := 8); port ( clk, reset: in STD_LOGIC; q: out STD_LOGIC_VECTOR(N-1 downto 0) ); end; architecture synth of counter is begin process(clk, reset) begin if reset then q <= (OTHERS => '0'); elsif rising_edge(clk) then q <= q + '1'; end if; end process; end; |
HDL Example 5.6 SHIFT REGISTER WITH PARALLEL LOAD |
module shiftreg #(parameter N = 8) ( input logic clk, input logic reset, load, input logic sin, input logic [N–1:0] d, output logic [N–1:0] q, output logic sout ); always_ff @(posedge clk, posedge reset) if (reset) q <= 0; else if (load) q <= d; else q <= {q[N–2:0], sin};
assign sout = q[N–1];
endmodule
|
module shiftreg #(parameter N = 8) ( input clk, input reset, load, input sin, input [N-1:0] d, output reg [N-1:0] q, output sout );
always @ ((posedge clk, posedge reset) if (reset) q <= 0; else if (load) q <= d; else q <= {q[N–2:0], sin};
assign sout = q[N–1];
endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity shiftreg is generic(N: integer := 8); port ( clk, reset: in STD_LOGIC; load, sin: in STD_LOGIC; d: in STD_LOGIC_VECTOR(N–1 downto 0); q: out STD_LOGIC_VECTOR(N–1 downto 0); sout: out STD_LOGIC ); end;
architecture synth of shiftreg is
begin
process(clk, reset) begin if reset = '1' then q <= (OTHERS => '0'); elsif rising_edge(clk) then if load then q <= d; else q <= q(N–2 downto 0) & sin; end if; end if; end process;
sout <= q(N–1);
end;
|
HDL Example 5.7 RAM |
module ram #(parameter N = 6, M = 32) ( input logic clk, input logic we, input logic [N–1:0] adr, input logic [M–1:0] din, output logic [M–1:0] dout );
logic [M–1:0] mem [2**N–1:0];
always_ff @(posedge clk)
if (we) mem [adr] <= din;
assign dout = mem[adr]; endmodule
|
module ram # (parameter N = 6, M = 32) ( input clk, input we, input [N-1:0] adr, input [M-1:0] din, output [M-1:0] dout );
reg [M-1:0] mem [2**N-1:0];
always @ (posedge clk) if (we) mem [adr] <= din;
assign dout mem[adr]; endmodule
|
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD_UNSIGNED.ALL; entity ram_array is generic(N: integer := 6; M: integer := 32); port ( clk, we: in STD_LOGIC; adr: in STD_LOGIC_VECTOR(N–1 downto 0); din: in STD_LOGIC_VECTOR(M–1 downto 0); dout: out STD_LOGIC_VECTOR(M–1 downto 0) ); end;
architecture synth of ram_array is type mem_array is array ((2**N–1) downto 0) of STD_LOGIC_VECTOR (M–1 downto 0); signal mem: mem_array;
begin process(clk) begin if rising_edge(clk) then if we = '1' then mem(TO_INTEGER(adr)) <= din; end if; end if; end process; dout <= mem(TO_INTEGER(adr)); end;
|
HDL Example 5.8 ROM |
module rom ( input logic [1:0] adr, output logic [2:0] dout ); always_comb case(adr) 2’b00: dout <= 3’b011; 2’b01: dout <= 3’b110; 2’b10: dout <= 3’b100; 2’b11: dout <= 3’b010; endcase endmodule |
module rom ( input [1:0] adr, output [2:0] dout ); always @ (adr) case(adr) 2’b00: dout <= 3’b011; 2’b01: dout <= 3’b110; 2’b10: dout <= 3’b100; 2’b11: dout <= 3’b010; endcase endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity rom is port ( adr: in STD_LOGIC_VECTOR(1 downto 0); dout: out STD_LOGIC_VECTOR(2 downto 0) ); end; architecture synth of rom is begin --process(all) begin--VHDL2008 process (adr) begin case adr is when "00" => dout <= "011"; when "01" => dout <= "110"; when "10" => dout <= "100"; when "11" => dout <= "010"; end case; end process; end; |
HDL Example 5.30 Shifter |
module leftshift2_32 ( input logic [31:0] a, output logic [31:0] y ); assign y = {a[29:0], 2'b0}; endmodule |
module leftshift2_32 ( input [31:0] a, output [31:0] y ); assign y = {a[29:0], 2'b0}; endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity leftshift2_32 is port ( a: in STD_LOGIC_VECTOR(31 downto 0); y: out STD_LOGIC_VECTOR(31 downto 0) ); end; architecture synth of leftshift2_32 is begin y <= a(29 downto 0) & "00"; end; |
HDL Example 5.31 4-bit Left and Right Rotator |
module ex5_14 ( input logic [3:0] a; output logic [3:0] right_rotated; output logic [3:0] left_rotated; input logic [1:0] shamt; ); // right rotated always_comb case(shamt) 2'b00: right_rotated = a; 2'b01: right_rotated = {a[0], a[3], a[2], a[1]}; 2'b10: right_rotated = {a[1], a[0], a[3], a[2]}; 2'b11: right_rotated = {a[2], a[1], a[0], a[3]}; default: right_rotated = 4'bxxxx; endcase // left rotated always_comb case(shamt) 2'b00: left_rotated = a; 2'b01: left_rotated = {a[2], a[1], a[0], a[3]}; 2'b10: left_rotated = {a[1], a[0], a[3], a[2]}; 2'b11: left_rotated = {a[0], a[3], a[2], a[1]}; default: left_rotated = 4'bxxxx; endcase endmodule |
module ex5_14 ( input [3:0] a; output [3:0] right_rotated; output [3:0] left_rotated; input [1:0] shamt; ); // right rotated always @ (*) // output logic (combinational) case(shamt) 2'b00: right_rotated = a; 2'b01: right_rotated = {a[0], a[3], a[2], a[1]}; 2'b10: right_rotated = {a[1], a[0], a[3], a[2]}; 2'b11: right_rotated = {a[2], a[1], a[0], a[3]}; default: right_rotated = 4'bxxxx; endcase // left rotated always @ (*) // output logic (combinational) case(shamt) 2'b00: left_rotated = a; 2'b01: left_rotated = {a[2], a[1], a[0], a[3]}; 2'b10: left_rotated = {a[1], a[0], a[3], a[2]}; 2'b11: left_rotated = {a[0], a[3], a[2], a[1]}; default: left_rotated = 4'bxxxx; endcase endmodule |
library IEEE; use IEEE.STD_LOGIC_1164.all; entity ex5_14 is port ( a: in STD_LOGIC_VECTOR(3 downto 0); right_rotated, left_rotated: out STD_LOGIC_VECTOR(3 downto 0); shamt: in STD_LOGIC_VECTOR(1 downto 0) ); end; architecture synth of ex5_14 is
begin architecture synth of ex5_14 is begin -- right-rotated process(all) begin -- VHDL 2008 case shamt is when "00" => right_rotated <= a; when "01" => right_rotated <= (a(0), a(3), a(2), a(1)); when "10" => right_rotated <= (a(1), a(0), a(3), a(2)); when "11" => right_rotated <= (a(2), a(1), a(0), a(3)); when others => right_rotated <= "XXXX"; end case; end process;
-- left-rotated process(all) begin case shamt is when "00" => left_rotated <= a; when "01" => left_rotated <= (a(2), a(1), a(0), a(3)); when "10" => left_rotated <= (a(1), a(0), a(3), a(2)); when "11" => left_rotated <= (a(0), a(3), a(2), a(1)); when others => left_rotated <= "XXXX"; end case; end process; end;
|