Appendix B: Sample Verilog Files for Modeling a Datapath
March 2001
Copyright (c) 2001 by Shing Ip Kong. All Rights Reserved.
Filed at: http://www.cs.wisc.edu/~markhill/kong/appendixB.html
Main text at: http://www.cs.wisc.edu/~markhill/kong
Appendix B: Sample Verilog Files for Modeling a Datapath $Revision: 1.1 $
-----------------------------------------------------------------------------
/****************************************************************************
*
* File Name: link_txdp.v
*
* Comment: Link Layer datapath for data transmission
*
* The datapath here excludes the part that is interfaced to the
* SERDES so everything here should run on the txclk4x.
*
* Author: Shing Kong
* Creation Date: 3/26/2001
*
* $Source: /proj/gemini/cvs_root/P2002/Notes/Style/appendixB,v $
* $Date: 2001/12/06 21:49:07 $
* $Revision: 1.1 $
*
*===========================================================================
* Copyright (c) 2001 by Shing Ip Kong. All Rights Reserved.
****************************************************************************/
/*
* $Id: appendixB,v 1.1 2001/12/06 21:49:07 kong Exp $
*/
`include "link_defs.v" // See ../../CommonFiles
module link_txdp (
// Outputs
txencdata,
next_txnrd,
// Inputs
tp_txdata,
r2t_rxsnprim,
r2t_rxsnrrdy,
r2t_rxsnrip,
r2t_rxsnrok,
r2t_rxsnrerr,
r2t_rxsndmat,
r2t_rxsnsync,
r2t_rxsnhold,
r2t_rxsnholda,
txscram_on,
txscr_init,
txscr_run,
txcrc_init,
txcrc_cal,
txsn_CRC,
txsn_data,
txsn_sync,
txsn_align,
txsn_xrdy,
txsn_sof,
txsn_holda,
txsn_hold,
txsn_eof,
txsn_wtrm,
cur_txnrd,
txclk4x,
lktx_reset);
/*
* Output to SERDES Interface
*/
output [0:39] txencdata; // Encoded transmit data
/*
* Output to the Link Layer Transmit Controller
*/
output next_txnrd; // New negative running disparity
/*
* Inputs from the Transport Layer
*/
input [31:0] tp_txdata;
/*
* Inputs from the Link Layer Receiver (link_rx.v)
* These signals have been synchronized with respect to txclk4x
*/
input r2t_rxsnprim; // RX controls the primitive sending
input r2t_rxsnrrdy; // RX sends the R_RDY primitive
input r2t_rxsnrip; // RX sends the R_RIP primitive
input r2t_rxsnrok; // RX sends the R_OK primitive
input r2t_rxsnrerr; // RX sends the R_ERR primitive
input r2t_rxsndmat; // RX sends the DMAT primitive
// The following primitives can be sent by either link_txctl or link_rxctl
input r2t_rxsnsync; // Sends the SYNC primitive
input r2t_rxsnhold; // Sends the HOLD primitive
input r2t_rxsnholda; // Sends the HOLDA primitive
/*
* Inputs from the Link Layer Transmit Controller (link_txctl.v)
*/
input txscram_on; // Turn on data scrambling
input txscr_init; // Initialize the scrambler
input txscr_run; // Increment the scrambler polynomial
input txcrc_init; // Initialize the CRC calculator
input txcrc_cal; // Update the CRC output
input txsn_CRC; // Send out the CRC pattern
input txsn_data; // Send data or CRC (nor primitive)
input txsn_sync; // TX sends the SYNC primitive
input txsn_align; // TX sends the ALIGN primitive
input txsn_xrdy; // TX sends the X_RDY primitive
input txsn_sof; // TX sends the SOF primitive
input txsn_holda; // TX sends the HOLDA primitive
input txsn_hold; // TX sends the HOLD primitive
input txsn_eof; // TX sends the EOF primitive
input txsn_wtrm; // TX sends the WTRM primitive
input cur_txnrd; // Current negative running disparity
/*
* Clocks and reset signals
*/
input txclk4x; // Transmit clock
input lktx_reset;
/*
* Interconnections within this portion of the datapath
*/
wire [`num_prim:0] // Number of primitives + D10.2
sel_prim; // Select the proper primitives
wire [31:0] scr_out; // Output of the scrambler
wire [31:0] crc_out; // Output of the CRC calculator
wire [31:0] prim_out; // Output of the Primitive generator
wire [31:0] crc_data; // Output of the CRC mux
wire [31:0] scram_data; // Scrambled data
wire [31:0] scrcrcdata; // Data or CRC after scrambled
wire [31:0] rawtxdata; // TX Data before 8b/10b coding
wire [31:0] clk_rawtxdata; // rawtxdata after registered
wire [0:39] enctxdata; // TX Data after 8b/10b coding
// Running negative disparity after encoding Byte 0, Byte 1, and Byte 2
wire [2:0] txnrd_byte;
wire clk_sendprim; // ~(txsn_data | txsn_CRC) registered
/*
* Simple logic to form the primitive selct vector
*
* First, deal with the 3 primitives that can be sent by either
* the Transmit (link_txctl) or the Receive (link_rxctl) controller
*
* Then we just need to proper connection with assign statements
*/
v_mux2e #(3) txrx_selmux (
{sel_prim[`B_HOLDA], sel_prim[`B_HOLD], sel_prim[`B_SYNC]},
r2t_rxsnprim,
{txsn_holda, txsn_hold, txsn_sync},
{r2t_rxsnholda, r2t_rxsnhold, r2t_rxsnsync});
// Primitive send by the Transmit Controller
assign sel_prim[`B_ALIGN] = txsn_align;
assign sel_prim[`B_X_RDY] = txsn_xrdy;
assign sel_prim[`B_SOF] = txsn_sof;
assign sel_prim[`B_EOF] = txsn_eof;
assign sel_prim[`B_WTRM] = txsn_wtrm;
// Primitive send by the Receive Controller
assign sel_prim[`B_R_RDY] = r2t_rxsnrrdy;
assign sel_prim[`B_R_IP] = r2t_rxsnrip;
assign sel_prim[`B_R_OK] = r2t_rxsnrok;
assign sel_prim[`B_R_ERR] = r2t_rxsnrerr;
assign sel_prim[`B_DMAT] = r2t_rxsndmat;
/*** Debug 4/13/2001: For now set these to zeros ***/
assign sel_prim[`B_CONT] = 1'b0;
assign sel_prim[`B_PMREQ_P] = 1'b0;
assign sel_prim[`B_PMREQ_S] = 1'b0;
assign sel_prim[`B_PMACK] = 1'b0;
assign sel_prim[`B_PMNAK] = 1'b0;
assign sel_prim[`B_D10_2] = 1'b0;
/*
* Scrambler
*/
l_scramble scrambler (
.scr_out (scr_out), .scr_in (32'hc2d2768d),
.scr_init (txscr_init), .scr_run (txscr_run),
.clk (txclk4x), .reset (lktx_reset));
/*
* CRC Calculator
*/
l_crccal crc_calculator (
.crc_out (crc_out),
.crc_in (32'h52325032), .datain (tp_txdata),
.crc_init (txcrc_init), .crc_cal (txcrc_cal),
.clk (txclk4x), .reset (lktx_reset));
// MUX to select between sending data or sending the CRC pattern
v_mux2e #(32) crc_mux (crc_data, txsn_CRC, tp_txdata, crc_out);
// Scramble the data by performing a bit-wise exclusive OR
assign scram_data = crc_data ^ scr_out;
// MUX to decide if we want to send the scrambled data
v_mux2e #(32) scramble_mux (scrcrcdata, txscram_on, crc_data, scram_data);
/*
* Generate the primitive (prime_out) based on the selection (sel_prim)
*/
l_primgen primgen (.prim_out (prim_out), .sel_prim (sel_prim));
// Decide if we should send the primitive out
v_mux2e #(32) prim_mux (rawtxdata, (txsn_data | txsn_CRC),
prim_out, scrcrcdata);
// Registered the data before sending them to the 8b/10b encoders
v_reg #(32) rawdata_ff (clk_rawtxdata, txclk4x, rawtxdata);
v_reg #(1) sendprim_ff (clk_sendprim, txclk4x, ~(txsn_data | txsn_CRC));
/*
* Perform the 8b/10b encoding. The encoder for Byte 0 (enc8b10bk)
* can encode the 8-bit D28_3 and D28_5 data words into the 10-bit
* K28_3 and K28_5 code words if the "K" control input is set to 1.
*/
enc8b10bk enc_byte0 ( // Byte 0 encoder
.do (enctxdata[0:9]), .nrdo (txnrd_byte[0]),
.di (clk_rawtxdata[7:0]), .nrdi (cur_txnrd),
.k (clk_sendprim));
enc8b10b enc_byte1 ( // Byte 1 Encoder
.do (enctxdata[10:19]), .nrdo (txnrd_byte[1]),
.di (clk_rawtxdata[15:8]), .nrdi (txnrd_byte[0]));
enc8b10b enc_byte2 ( // Byte 2 Encoder
.do (enctxdata[20:29]), .nrdo (txnrd_byte[2]),
.di (clk_rawtxdata[23:16]), .nrdi (txnrd_byte[1]));
enc8b10b enc_byte3 ( // Byte 3 Encoder
.do (enctxdata[30:39]), .nrdo (next_txnrd),
.di (clk_rawtxdata[31:24]), .nrdi (txnrd_byte[2]));
v_reg #(40) encdata_ff (txencdata, txclk4x, enctxdata);
endmodule // link_txdp
/****************************************************************************
*
* File Name: link_library.v
*
* Comment: Components for the Link layer datapath.
*
* Author: Shing Kong
* Creation Date: 1/25/2001
*
* $Source: /proj/gemini/cvs_root/P2002/Notes/Style/appendixB,v $
* $Date: 2001/12/06 21:49:07 $
* $Revision: 1.1 $
*
*===========================================================================
* Copyright (c) 2001 by Shing Ip Kong. All Rights Reserved.
****************************************************************************/
/*
* $Id: appendixB,v 1.1 2001/12/06 21:49:07 kong Exp $
*/
/****************************************************************************
* All the library elements in this file have names start with: "l_"
***************************************************************************/
`include "link_defs.v"
/****************************************************************************
* l_scramble: 32-bit scrambler that can be:
* a. Reset to all zeros asynchronously
* b. Load a fix pattern synchronously.
* c. Keep its old value if scramble is not enable.
* d. Update its output synchronously based on a LFSR algorithm.
***************************************************************************/
module l_scramble (scr_out, scr_in, scr_init, scr_run, clk, reset);
output [31:0] scr_out; // Scrambler's output
input [31:0] scr_in; // Initial pattern to be loaded
input scr_init; // Load the initial pattern
input scr_run; // Update scr_out based on a LFSR
input clk;
input reset;
reg [31:0] scram; // Scramble data pattern
reg a15, a14, a13, // Intermediate scramble bits
a12, a11, a10,
a9, a8, a7, a6, a5, a4, a3, a2, a1, a0;
wire [31:0] runmuxout; // Output of the scr_run MUX
wire [31:0] lastmux; // Output of the final MUX
/*
* Combinational logic to produce the scramble pattern,
* which should be updated whenever scr_out changes.
* This logic was copied from Frank Lee's scramble.v
*/
always @(scr_out) begin
a15 = scr_out[31] ^ scr_out[29] ^ scr_out[20] ^ scr_out[16];
a14 = scr_out[30] ^ scr_out[21] ^ scr_out[17];
a13 = scr_out[31] ^ scr_out[22] ^ scr_out[18];
a12 = scr_out[23] ^ scr_out[19];
a11 = scr_out[24] ^ scr_out[20];
a10 = scr_out[25] ^ scr_out[21];
a9 = scr_out[26] ^ scr_out[22];
a8 = scr_out[27] ^ scr_out[23];
a7 = scr_out[28] ^ scr_out[24];
a6 = scr_out[29] ^ scr_out[25];
a5 = scr_out[30] ^ scr_out[26];
a4 = scr_out[31] ^ scr_out[27];
a3 = scr_out[28];
a2 = scr_out[29];
a1 = scr_out[30];
a0 = scr_out[31];
scram[31] = a15^a14^ a12^a11^a10^ a7^a6^a5^ a0;
scram[30] = a15^ a13^a12^a11^ a8^a7^a6^ a1^a0;
scram[29] = a14^a13^a12^ a9^a8^a7^ a2^a1;
scram[28] = a15^a14^a13^ a10^a9^a8^ a3^a2;
scram[27] = a15^a14^ a11^a10^a9^ a4^a3^ a0;
scram[26] = a15^ a12^a11^a10^ a5^a4^ a1^a0;
scram[25] = a13^a12^a11^ a6^a5^ a2^a1;
scram[24] = a14^a13^a12^ a7^a6^ a3^a2^ a0;
scram[23] = a15^a14^a13^ a8^a7^ a4^a3^ a1^a0;
scram[22] = a15^a14^ a9^a8^ a5^a4^ a2^a1^a0;
scram[21] = a15^ a10^a9^ a6^a5^ a3^a2^a1;
scram[20] = a11^a10^ a7^a6^ a4^a3^a2;
scram[19] = a12^a11^ a8^a7^ a5^a4^a3^ a0;
scram[18] = a13^a12^ a9^a8^ a6^a5^a4^ a1;
scram[17] = a14^a13^ a10^a9^ a7^a6^a5^ a2^ a0;
scram[16] = a15^a14^ a11^a10^ a8^a7^a6^ a3^ a1^a0;
scram[15] = a15^ a12^a11^ a9^a8^a7^ a4^ a2^a1^a0;
scram[14] = a13^a12^ a10^a9^a8^ a5^ a3^a2^a1;
scram[13] = a14^a13^ a11^a10^a9^ a6^ a4^a3^a2;
scram[12] = a15^a14^ a12^a11^a10^ a7^ a5^a4^a3;
scram[11] = a15^ a13^a12^a11^ a8^ a6^a5^a4;
scram[10] = a14^a13^a12^ a9^ a7^a6^a5;
scram[9] = a15^a14^a13^ a10^ a8^a7^a6;
scram[8] = a15^a14^ a11^ a9^a8^a7;
scram[7] = a15^ a12^ a10^a9^a8;
scram[6] = a13^ a11^a10^a9;
scram[5] = a14^ a12^a11^a10;
scram[4] = a15^ a13^a12^a11;
scram[3] = a14^a13^a12;
scram[2] = a15^a14^a13;
scram[1] = a15^a14;
scram[0] = a15;
end // Scrambling logic
/* Priority:
* scram scr_out -------------------------------
* | | reset (asynchronous): highest
* +---v---v---+ scr_init (synchronous): middle
* scr_run-->\S 1 0 / scr_run (synchronous): lowest
* +---+---+ scr_in
* | |
* +---v-------v---+
* \ 0 1 S/<--scr_init (higher priority than scr_run)
* +-----+-----+
* |
* v
* lastmux
*/
v_mux2e #(32) run_mux (runmuxout, scr_run, scr_out, scram);
v_mux2e #(32) init_mux (lastmux, scr_init, runmuxout, scr_in);
v_regre #(32) scr_ff (scr_out, clk, lastmux, (scr_run | scr_init), reset);
endmodule // l_scramble
/****************************************************************************
* l_crccal: 32-bit CRC calculator that can be:
* a. Reset to all zeros asynchronously
* b. Load a fix pattern synchronously.
* c. Keep its old value if CRC calculation is not enable.
* d. Update its output synchronously based on its input
***************************************************************************/
module l_crccal (crc_out, crc_in, datain, crc_init, crc_cal, clk, reset);
output [31:0] crc_out; // CRC calculator's output
input [31:0] crc_in; // Initial patern to be loaded
input [31:0] datain; // Data contribute to CRC calculation
input crc_init; // Load the initial pattern
input crc_cal; // Calculate crc_out based on a LFSR
input clk;
input reset;
reg [31:0] x; // Temporary variable for CRC
reg [31:0] crc; // Output of the CRC random logic
wire [31:0] runmuxout; // Output of the crc_cal MUX
wire [31:0] lastmux; // Output of the final MUX
/*
* Combinational logic to calculates the CRC output.
* Its output should be updated whenever crc_out or datain changes.
* This logic was copied from Frank Lee's satacrc.v
*/
always @(crc_out or datain) begin
x = datain ^ crc_out;
crc = (x[0]? 32'b00000100110000010001110110110111: 32'b0)
^ (x[1]? 32'b00001001100000100011101101101110: 32'b0)
^ (x[2]? 32'b00010011000001000111011011011100: 32'b0)
^ (x[3]? 32'b00100110000010001110110110111000: 32'b0)
^ (x[4]? 32'b01001100000100011101101101110000: 32'b0)
^ (x[5]? 32'b10011000001000111011011011100000: 32'b0)
^ (x[6]? 32'b00110100100001100111000001110111: 32'b0)
^ (x[7]? 32'b01101001000011001110000011101110: 32'b0)
^ (x[8]? 32'b11010010000110011100000111011100: 32'b0)
^ (x[9]? 32'b10100000111100101001111000001111: 32'b0)
^ (x[10]? 32'b01000101001001000010000110101001: 32'b0)
^ (x[11]? 32'b10001010010010000100001101010010: 32'b0)
^ (x[12]? 32'b00010000010100011001101100010011: 32'b0)
^ (x[13]? 32'b00100000101000110011011000100110: 32'b0)
^ (x[14]? 32'b01000001010001100110110001001100: 32'b0)
^ (x[15]? 32'b10000010100011001101100010011000: 32'b0)
^ (x[16]? 32'b00000001110110001010110010000111: 32'b0)
^ (x[17]? 32'b00000011101100010101100100001110: 32'b0)
^ (x[18]? 32'b00000111011000101011001000011100: 32'b0)
^ (x[19]? 32'b00001110110001010110010000111000: 32'b0)
^ (x[20]? 32'b00011101100010101100100001110000: 32'b0)
^ (x[21]? 32'b00111011000101011001000011100000: 32'b0)
^ (x[22]? 32'b01110110001010110010000111000000: 32'b0)
^ (x[23]? 32'b11101100010101100100001110000000: 32'b0)
^ (x[24]? 32'b11011100011011011001101010110111: 32'b0)
^ (x[25]? 32'b10111100000110100010100011011001: 32'b0)
^ (x[26]? 32'b01111100111101010100110000000101: 32'b0)
^ (x[27]? 32'b11111001111010101001100000001010: 32'b0)
^ (x[28]? 32'b11110111000101000010110110100011: 32'b0)
^ (x[29]? 32'b11101010111010010100011011110001: 32'b0)
^ (x[30]? 32'b11010001000100111001000001010101: 32'b0)
^ (x[31]? 32'b10100110111001100011110100011101: 32'b0);
end // End of the combinational logic that calculates the CRC
/* Priority:
* crc crc_out -------------------------------
* | | reset (asynchronous): highest
* +---v---v---+ crc_init (synchronous): middle
* crc_cal-->\S 1 0 / crc_cal (synchronous): lowest
* +---+---+ crc_in
* | |
* +---v-------v---+
* \ 0 1 S/<--crc_init (higher priority than crc_cal)
* +-----+-----+
* |
* v
* lastmux
*/
v_mux2e #(32) run_mux (runmuxout, crc_cal, crc_out, crc);
v_mux2e #(32) init_mux (lastmux, crc_init, runmuxout, crc_in);
v_regre #(32) crc_ff (crc_out, clk, lastmux, (crc_cal | crc_init), reset);
endmodule // l_crccal
/****************************************************************************
* l_primgen: 32-bit primitive generator
* This 32-bit primitive must be encoded by the 8-bit/10-bit encoder
* to become the actual 40-bit SATA primitives.
*
* One interesting feature here is that Byte 0 of the 32-bit primitive
* is either D28.3 or D28.5 and when it is encoded to K28.3 and K28.5
* by a 8-bit/10-bit encoder with the control bit (K) set to 1.
*
***************************************************************************/
module l_primgen (prim_out, sel_prim);
output [31:0] prim_out; // 32-bit primitive
input [`num_prim:0] sel_prim; // Primitive + D10.2 select
reg [31:0] prim_out;
always @(sel_prim) begin
if (sel_prim[`B_ALIGN]) begin
//******** {Byte 3, Byte 2, Byte 1, Byte 0}
prim_out = {`D27_3, `D10_2, `D10_2, `D28_5};
end
else if (sel_prim[`B_SYNC]) begin
prim_out = {`D21_5, `D21_5, `D21_4, `D28_3};
end
else if (sel_prim[`B_CONT]) begin
prim_out = {`D25_4, `D25_4, `D10_5, `D28_3};
end
else if (sel_prim[`B_HOLD]) begin
prim_out = {`D21_6, `D21_6, `D10_5, `D28_3};
end
else if (sel_prim[`B_HOLDA]) begin
prim_out = {`D21_4, `D21_4, `D10_5, `D28_3};
end
else if (sel_prim[`B_R_RDY]) begin
prim_out = {`D10_2, `D10_2, `D21_4, `D28_3};
end
else if (sel_prim[`B_R_IP]) begin
prim_out = {`D21_2, `D21_2, `D21_5, `D28_3};
end
else if (sel_prim[`B_R_OK]) begin
prim_out = {`D21_1, `D21_1, `D21_5, `D28_3};
end
else if (sel_prim[`B_R_ERR]) begin
prim_out = {`D22_2, `D22_2, `D21_5, `D28_3};
end
else if (sel_prim[`B_X_RDY]) begin
prim_out = {`D23_2, `D23_2, `D21_5, `D28_3};
end
else if (sel_prim[`B_SOF]) begin
prim_out = {`D23_1, `D23_1, `D21_5, `D28_3};
end
else if (sel_prim[`B_EOF]) begin
prim_out = {`D21_6, `D21_6, `D21_5, `D28_3};
end
else if (sel_prim[`B_DMAT]) begin
prim_out = {`D22_1, `D22_1, `D21_5, `D28_3};
end
else if (sel_prim[`B_WTRM]) begin
prim_out = {`D24_2, `D24_2, `D21_5, `D28_3};
end
else if (sel_prim[`B_PMREQ_P]) begin
prim_out = {`D23_0, `D23_0, `D21_5, `D28_3};
end
else if (sel_prim[`B_PMREQ_S]) begin
prim_out = {`D21_3, `D21_3, `D21_4, `D28_3};
end
else if (sel_prim[`B_PMACK]) begin
prim_out = {`D21_4, `D21_4, `D21_4, `D28_3};
end
else if (sel_prim[`B_PMNAK]) begin
prim_out = {`D21_7, `D21_7, `D21_4, `D28_3};
end
else if (sel_prim[`B_D10_2]) begin
// Special four D10_2 words in a row
prim_out = {`D10_2, `D10_2, `D10_2, `D10_2};
end
else begin // None are selected: send ALIGN
prim_out = {`D27_3, `D10_2, `D10_2, `D28_5};
end
end
endmodule // l_primgen
/****************************************************************************
* l_primdec: primitive decoder
***************************************************************************/
module l_primdec (prim_vector, prim_in, k28_3, k28_5);
output [`num_prim-1:0]
prim_vector; // Primitive vector
input [31:8] prim_in; // Bytes 3, 2, and 1 of the primitive
input k28_3; // Byte 0 is a K28_3 character
input k28_5; // Byte 0 is a K28_5 character
wire [`num_prim-1:0]
maybe; // May be vector
// Basic primitives
v_comparator #(24) align_cmp (
.out (maybe[`B_ALIGN]),
.in1 (prim_in), .in2 ({`D27_3, `D10_2, `D10_2}));
assign prim_vector[`B_ALIGN] = maybe[`B_ALIGN] & k28_5;
v_comparator #(24) sync_cmp (
.out (maybe[`B_SYNC]),
.in1 (prim_in), .in2 ({`D21_5, `D21_5, `D21_4}));
assign prim_vector[`B_SYNC] = maybe[`B_SYNC] & k28_3;
v_comparator #(24) cont_cmp (
.out (maybe[`B_CONT]),
.in1 (prim_in), .in2 ({`D25_4, `D25_4, `D10_5}));
assign prim_vector[`B_CONT] = maybe[`B_CONT] & k28_3;
// Flow control primitives
v_comparator #(24) hold_cmp (
.out (maybe[`B_HOLD]),
.in1 (prim_in), .in2 ({`D21_6, `D21_6, `D10_5}));
assign prim_vector[`B_HOLD] = maybe[`B_HOLD] & k28_3;
v_comparator #(24) holda_cmp (
.out (maybe[`B_HOLDA]),
.in1 (prim_in), .in2 ({`D21_4, `D21_4, `D10_5}));
assign prim_vector[`B_HOLDA] = maybe[`B_HOLDA] & k28_3;
v_comparator #(24) r_rdy_cmp (
.out (maybe[`B_R_RDY]),
.in1 (prim_in), .in2 ({`D10_2, `D10_2, `D21_4}));
assign prim_vector[`B_R_RDY] = maybe[`B_R_RDY] & k28_3;
v_comparator #(24) r_ip_cmp (
.out (maybe[`B_R_IP]),
.in1 (prim_in), .in2 ({`D21_2, `D21_2, `D21_5}));
assign prim_vector[`B_R_IP] = maybe[`B_R_IP] & k28_3;
v_comparator #(24) r_ok_cmp (
.out (maybe[`B_R_OK]),
.in1 (prim_in), .in2 ({`D21_1, `D21_1, `D21_5}));
assign prim_vector[`B_R_OK] = maybe[`B_R_OK] & k28_3;
v_comparator #(24) r_err_cmp (
.out (maybe[`B_R_ERR]),
.in1 (prim_in), .in2 ({`D22_2, `D22_2, `D21_5}));
assign prim_vector[`B_R_ERR] = maybe[`B_R_ERR] & k28_3;
v_comparator #(24) x_rdy_cmp (
.out (maybe[`B_X_RDY]),
.in1 (prim_in), .in2 ({`D23_2, `D23_2, `D21_5}));
assign prim_vector[`B_X_RDY] = maybe[`B_X_RDY] & k28_3;
v_comparator #(24) sof_cmp (
.out (maybe[`B_SOF]),
.in1 (prim_in), .in2 ({`D23_1, `D23_1, `D21_5}));
assign prim_vector[`B_SOF] = maybe[`B_SOF] & k28_3;
v_comparator #(24) eof_cmp (
.out (maybe[`B_EOF]),
.in1 (prim_in), .in2 ({`D21_6, `D21_6, `D21_5}));
assign prim_vector[`B_EOF] = maybe[`B_EOF] & k28_3;
v_comparator #(24) dmat_cmp (
.out (maybe[`B_DMAT]),
.in1 (prim_in), .in2 ({`D22_1, `D22_1, `D21_5}));
assign prim_vector[`B_DMAT] = maybe[`B_DMAT] & k28_3;
v_comparator #(24) wtrm_cmp (
.out (maybe[`B_WTRM]),
.in1 (prim_in), .in2 ({`D24_2, `D24_2, `D21_5}));
assign prim_vector[`B_WTRM] = maybe[`B_WTRM] & k28_3;
// Power management primitives
v_comparator #(24) pmreq_p_cmp (
.out (maybe[`B_PMREQ_P]),
.in1 (prim_in), .in2 ({`D23_0, `D23_0, `D21_5}));
assign prim_vector[`B_PMREQ_P] = maybe[`B_PMREQ_P] & k28_3;
v_comparator #(24) pmreq_s_cmp (
.out (maybe[`B_PMREQ_S]),
.in1 (prim_in), .in2 ({`D21_3, `D21_3, `D21_4}));
assign prim_vector[`B_PMREQ_S] = maybe[`B_PMREQ_S] & k28_3;
v_comparator #(24) pmack_cmp (
.out (maybe[`B_PMACK]),
.in1 (prim_in), .in2 ({`D21_4, `D21_4, `D21_4}));
assign prim_vector[`B_PMACK] = maybe[`B_PMACK] & k28_3;
v_comparator #(24) pmnak_cmp (
.out (maybe[`B_PMNAK]),
.in1 (prim_in), .in2 ({`D21_7, `D21_7, `D21_4}));
assign prim_vector[`B_PMNAK] = maybe[`B_PMNAK] & k28_3;
endmodule // l_primgen
/****************************************************************************
*
* File Name: link_defs.v
*
* Comment: Definitions for the Link Layer
*
* Author: Shing Kong
* Creation Date: 1/29/2001
*
* $Source: /proj/gemini/cvs_root/P2002/Notes/Style/appendixB,v $
* $Date: 2001/12/06 21:49:07 $
* $Revision: 1.1 $
*
*===========================================================================
* Copyright (c) 2001 by Shing Ip Kong. All Rights Reserved.
****************************************************************************/
/*
* $Id: appendixB,v 1.1 2001/12/06 21:49:07 kong Exp $
*/
/*
* Number of primitives and the bit position of the 1-hot encoded vector
*/
`define num_prim 18
// Basic Primitives
`define B_ALIGN 0
`define B_SYNC 1
`define B_CONT 2
// Flow Control Primitives
`define B_HOLD 3
`define B_HOLDA 4
`define B_R_RDY 5
`define B_R_IP 6
`define B_R_OK 7
`define B_R_ERR 8
`define B_X_RDY 9
`define B_SOF 10
`define B_EOF 11
`define B_DMAT 12
`define B_WTRM 13
// Power Management Primitives
`define B_PMREQ_P 14
`define B_PMREQ_S 15
`define B_PMACK 16
`define B_PMNAK 17
// Special patterns (not a primitive) to be generated
// by the l_primgen: four consecutive D10_2's
`define B_D10_2 18
/*
* Define the 8-bit pattern for the primitives
*
* Note: The 8-bit D28_3 and D28_5 will be encoded into the 10-bit
* K28_3 and K28_5 patterns by the 8B/10B encoder with its
* control bit (K) set to 1.
*/
`define D10_2 8'b010_01010 // 0x4A
`define D10_4 8'b100_01010 // 0x8A
`define D10_5 8'b101_01010 // 0xAA
`define D21_1 8'b001_10101 // 0x35
`define D21_2 8'b010_10101 // 0x55
`define D21_3 8'b011_10101 // 0x75
`define D21_4 8'b100_10101 // 0x95
`define D21_5 8'b101_10101 // 0xB5
`define D21_6 8'b110_10101 // 0xD5
`define D21_7 8'b111_10101 // 0xF5
`define D22_1 8'b001_10110 // 0x36
`define D22_2 8'b010_10110 // 0x56
`define D23_0 8'b000_10111 // 0x17
`define D23_1 8'b001_10111 // 0x37
`define D23_2 8'b010_10111 // 0x57
`define D24_2 8'b010_11000 // 0x58
`define D25_4 8'b100_11001 // 0x99
`define D27_3 8'b011_11011 // 0x7B
`define D27_4 8'b100_11011 // 0x9B
`define D28_3 8'b011_11100 // 0x7C
`define D28_5 8'b101_11100 // 0xBC
/*
* Define the bit position and state values for the transmit finite state
* machine (FSM in the link_txctl). This FSM implements the "Link Idle
* State Diagram" (P. 145 of the SATA V1 Spec.) and the "Link Transmit
* State Diagram" (P. 148 of the SATA V1 Spec).
*
* The two states below are not shown explicitly in the two state diagrams
* described above:
* BUSYRCV: we have kicked off the receive finite state machine
* (see below) and therefore cannot transmit any of our own data.
*
* POWERDOWN: we have entered the power saving states, which will
* be handled by the Power Management State machine.
*/
// Number of TX states and bit position of the 1-hot state encoding
`define num_lktxstate 15
`define B_NOCOMM 0
`define B_SENDALIGN 1
`define B_NOCOMMERR 2
`define B_TXIDLE 3
`define B_HSENDCHKRDY 4
`define B_DSENDCHKRDY 5
`define B_SENDSOF 6
`define B_SENDDATA 7
`define B_RCVRHOLD 8
`define B_SENDHOLD 9
`define B_SENDCRC 10
`define B_SENDEOF 11
`define B_WAIT 12
`define B_BUSYRCV 13
`define B_POWERDOWN 14
// State Values
`define RESET 15'h0000 // All bits are zeros
`define NOCOMM 15'h0001 // Bit 0 is set
`define SENDALIGN 15'h0002 // Bit 1 is set
`define NOCOMMERR 15'h0004 // Bit 2 is set
`define TXIDLE 15'h0008
`define HSENDCHKRDY 15'h0010
`define DSENDCHKRDY 15'h0020
`define SENDSOF 15'h0040
`define SENDDATA 15'h0080
`define RCVRHOLD 15'h0100
`define SENDHOLD 15'h0200
`define SENDCRC 15'h0400
`define SENDEOF 15'h0800
`define WAIT 15'h1000
`define BUSYRCV 15'h2000 // Link layer is busy receiving data
`define POWERSAVE 15'h4000 // Link layer is power down
/*
* Define the state values and bit position for the receive finite state
* machine (FSM in the link_rxctl). This FSM implements the "Link
* Receive State Diagram" (P. 154 of the SATA V1 Spec).
*/
// Number of RX states and bit position of the 1-hot state encoding
`define num_lkrxstate 11
`define B_RXIDLE 0
`define B_RCVCHKRDY 1
`define B_RCVWAITFIFO 2
`define B_RCVDATA 3
`define B_RXSNHOLD 4
`define B_RXSNHOLDA 5
`define B_RCVEOF 6
`define B_GOODCRC 7
`define B_GOODEND 8
`define B_BADEND 9
`define B_WAITTXID 10 // Wait for TX FSM to return to idle state
// State Values
`define RXIDLE 11'h001
`define RCVCHKRDY 11'h002
`define RCVWAITFIFO 11'h004
`define RCVDATA 11'h008
`define RXSNHOLD 11'h010
`define RXSNHOLDA 11'h020
`define RCVEOF 11'h040
`define GOODCRC 11'h080
`define GOODEND 11'h100
`define BADEND 11'h200
`define WAITTXID 11'h400