HOST/FPGA REGISTER SPACE MODULE
(Last Modified: 04 November 2010 06:09:00 PM )
// ======================================================================
// GLOBAL HOST/FPGA REGISTER SPACE
// ======================================================================
// HOST register outputs
wire [7:0] HR00, HR01, HR02, HR03, HR04, HR05, HR06, HR07;
wire [7:0] HR08, HR09, HR0A, HR0B, HR0C, HR0D, HR0E, HR0F;
wire [7:0] HR10, HR11, HR12, HR13, HR14, HR15, HR16, HR17;
wire [7:0] HR18, HR19, HR1A, HR1B, HR1C, HR1D, HR1E, HR1F;
wire [7:0] HR20, HR21, HR22, HR23, HR24, HR25, HR26, HR27;
wire [7:0] HR28, HR29, HR2A, HR2B, HR2C, HR2D, HR2E, HR2F;
wire [7:0] HR30, HR31, HR32, HR33, HR34, HR35, HR36, HR37;
wire [7:0] HR38, HR39, HR3A, HR3B, HR3C, HR3D, HR3E, HR3F;
// FPGA register inputs
wire [7:0] FR00, FR01, FR02, FR03, FR04, FR05, FR06, FR07;
wire [7:0] FR08, FR09, FR0A, FR0B, FR0C, FR0D, FR0E, FR0F;
wire [7:0] FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17;
wire [7:0] FR18, FR19, FR1A, FR1B, FR1C, FR1D, FR1E, FR1F;
wire [7:0] FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27;
wire [7:0] FR28, FR29, FR2A, FR2B, FR2C, FR2D, FR2E, FR2F;
wire [7:0] FR30, FR31, FR32, FR33, FR34, FR35, FR36, FR37;
wire [7:0] FR38, FR39, FR3A, FR3B, FR3C, FR3D, FR3E, FR3F;
RegSpace REGS
(
// HOST register outputs
.HR00(HR00), .HR01(HR01), .HR02(HR02), .HR03(HR03),
.HR04(HR04), .HR05(HR05), .HR06(HR06), .HR07(HR07),
.HR08(HR08), .HR09(HR09), .HR0A(HR0A), .HR0B(HR0B),
.HR0C(HR0C), .HR0D(HR0D), .HR0E(HR0E), .HR0F(HR0F),
.HR10(HR10), .HR11(HR11), .HR12(HR12), .HR13(HR13),
.HR14(HR14), .HR15(HR15), .HR16(HR16), .HR17(HR17),
.HR18(HR18), .HR19(HR19), .HR1A(HR1A), .HR1B(HR1B),
.HR1C(HR1C), .HR1D(HR1D), .HR1E(HR1E), .HR1F(HR1F),
.HR20(HR20), .HR21(HR21), .HR22(HR22), .HR23(HR23),
.HR24(HR24), .HR25(HR25), .HR26(HR26), .HR27(HR27),
.HR28(HR28), .HR29(HR29), .HR2A(HR2A), .HR2B(HR2B),
.HR2C(HR2C), .HR2D(HR2D), .HR2E(HR2E), .HR2F(HR2F),
.HR30(HR30), .HR31(HR31), .HR32(HR32), .HR33(HR33),
.HR34(HR34), .HR35(HR35), .HR36(HR36), .HR37(HR37),
.HR38(HR38), .HR39(HR39), .HR3A(HR3A), .HR3B(HR3B),
.HR3C(HR3C), .HR3D(HR3D), .HR3E(HR3E), .HR3F(HR3F),
// FPGA register inputs
.FR00(FR00), .FR01(FR01), .FR02(FR02), .FR03(FR03),
.FR04(FR04), .FR05(FR05), .FR06(FR06), .FR07(FR07),
.FR08(FR08), .FR09(FR09), .FR0A(FR0A), .FR0B(FR0B),
.FR0C(FR0C), .FR0D(FR0D), .FR0E(FR0E), .FR0F(FR0F),
.FR10(FR10), .FR11(FR11), .FR12(FR12), .FR13(FR13),
.FR14(FR14), .FR15(FR15), .FR16(FR16), .FR17(FR17),
.FR18(FR18), .FR19(FR19), .FR1A(FR1A), .FR1B(FR1B),
.FR1C(FR1C), .FR1D(FR1D), .FR1E(FR1E), .FR1F(FR1F),
.FR20(FR20), .FR21(FR21), .FR22(FR22), .FR23(FR23),
.FR24(FR24), .FR25(FR25), .FR26(FR26), .FR27(FR27),
.FR28(FR28), .FR29(FR29), .FR2A(FR2A), .FR2B(FR2B),
.FR2C(FR2C), .FR2D(FR2D), .FR2E(FR2E), .FR2F(FR2F),
.FR30(FR30), .FR31(FR31), .FR32(FR32), .FR33(FR33),
.FR34(FR34), .FR35(FR35), .FR36(FR36), .FR37(FR37),
.FR38(FR38), .FR39(FR39), .FR3A(FR3A), .FR3B(FR3B),
.FR3C(FR3C), .FR3D(FR3D), .FR3E(FR3E), .FR3F(FR3F),
// Control Interface
.regWA(regWA), // HOST Register Write Address
.regWD(regWD), // HOST Register Write Data
.regWS(regWS), // HOST Register Write Strobe
.regRA(regRA), // Register Read Address
.regRD(regRD), // Register Read Data
// Global clock and reset
.rst(rst), .clk(clk)
);
The HOST/FPGA Register Space module provides a simple boundary between the internal FPGA signals and the external HOST system. The 256-byte register space is partitioned into a lower half and an upper half, each implemented as a separate bank of dual-port RAM. The lower half is writable from the HOST and statically readable by the FPGA while the upper half is statically writable by the FPGA and readable by the HOST. The HOST can also read back any of the registers in the lower memory.
Presently only half of each bank is implemented resulting in 64 registers in each direction. The naming convention for the registers is HRxx for the HOST-writable registers and FRxx for the FPGA writable registers where "xx" is the register address, relative to the base of that partition, expressed in hexadecimal.
To write to one of the Host Registers, the 8-bit register address is placed
on the reg
WA
port and the data to be
written is placed on the regWD
port. The regW
S
is then strobed HI to update the register contents (upon the next rising clock
edge). The write strobe line must be returned LO to prior to changing the
address.
To read from any register, the 8-bit register address is placed on the
regRA
port and the data is made available on the regRD
port on the next rising edge of the global clock.
Attempts to write to non-HOST registers are ignored. while attempts to read from unimplemented registers are mapped back into the implemented space for the corresponding bank.
The following is the Verilog code contained in the file regspace.v.
module RegSpace(
// HOST register outputs
HR00, HR01, HR02, HR03, HR04, HR05, HR06, HR07,
HR08, HR09, HR0A, HR0B, HR0C, HR0D, HR0E, HR0F,
HR10, HR11, HR12, HR13, HR14, HR15, HR16, HR17,
HR18, HR19, HR1A, HR1B, HR1C, HR1D, HR1E, HR1F,
HR20, HR21, HR22, HR23, HR24, HR25, HR26, HR27,
HR28, HR29, HR2A, HR2B, HR2C, HR2D, HR2E, HR2F,
HR30, HR31, HR32, HR33, HR34, HR35, HR36, HR37,
HR38, HR39, HR3A, HR3B, HR3C, HR3D, HR3E, HR3F,
// FPGA register inputs
FR00, FR01, FR02, FR03, FR04, FR05, FR06, FR07,
FR08, FR09, FR0A, FR0B, FR0C, FR0D, FR0E, FR0F,
FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17,
FR18, FR19, FR1A, FR1B, FR1C, FR1D, FR1E, FR1F,
FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27,
FR28, FR29, FR2A, FR2B, FR2C, FR2D, FR2E, FR2F,
FR30, FR31, FR32, FR33, FR34, FR35, FR36, FR37,
FR38, FR39, FR3A, FR3B, FR3C, FR3D, FR3E, FR3F,
// Control Interface
regWA, regWD, regRA, regRD, regWS,
// Global clock and reset
rst, clk
);
// ======================================================================
// Parameter Definitions
// ----------------------------------------------------------------------
parameter LO = 1'b0, HI = 1'b1; // Logic levels
parameter REGWIDTH = 8; // Number of bits in each register
parameter REGDEPTH = 64; // Number of registers in each bank
parameter REGLOG2DEPTH = 6; // Number of sig bits in register address
// ======================================================================
// I/O Port Definitions
// ----------------------------------------------------------------------
// HOST memory outputs
output [7:0] HR00, HR01, HR02, HR03, HR04, HR05, HR06, HR07;
output [7:0] HR08, HR09, HR0A, HR0B, HR0C, HR0D, HR0E, HR0F;
output [7:0] HR10, HR11, HR12, HR13, HR14, HR15, HR16, HR17;
output [7:0] HR18, HR19, HR1A, HR1B, HR1C, HR1D, HR1E, HR1F;
output [7:0] HR20, HR21, HR22, HR23, HR24, HR25, HR26, HR27;
output [7:0] HR28, HR29, HR2A, HR2B, HR2C, HR2D, HR2E, HR2F;
output [7:0] HR30, HR31, HR32, HR33, HR34, HR35, HR36, HR37;
output [7:0] HR38, HR39, HR3A, HR3B, HR3C, HR3D, HR3E, HR3F;
// FPGA memory inputs
input [7:0] FR00, FR01, FR02, FR03, FR04, FR05, FR06, FR07;
input [7:0] FR08, FR09, FR0A, FR0B, FR0C, FR0D, FR0E, FR0F;
input [7:0] FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17;
input [7:0] FR18, FR19, FR1A, FR1B, FR1C, FR1D, FR1E, FR1F;
input [7:0] FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27;
input [7:0] FR28, FR29, FR2A, FR2B, FR2C, FR2D, FR2E, FR2F;
input [7:0] FR30, FR31, FR32, FR33, FR34, FR35, FR36, FR37;
input [7:0] FR38, FR39, FR3A, FR3B, FR3C, FR3D, FR3E, FR3F;
// Control Interface
input [(REGWIDTH-1):0] regWA, // HOST Register Write Address
input [(REGWIDTH-1):0] regWD, // HOST Register Write Data
input regWS, // HOST Register Write Strobe
input [(REGWIDTH-1):0] regRA, // Register Read Address
output [(REGWIDTH-1):0] regRD, // Register Read Data
// Global reset and clock
input rst, clk;
// ======================================================================
// Register Bank Instantiation
// ----------------------------------------------------------------------
// HOST Register Array (written via serial interface)
reg [(REGWIDTH-1):0] HOSTregister[(REGDEPTH-1):0];
// FPGA Register Array (written directly by FPGA)
reg [(REGWIDTH-1):0] FPGAregister[(REGDEPTH-1):0];
// ======================================================================
// FPGA Register Read Process
// ----------------------------------------------------------------------
reg [(REGLOG2DEPTH-1):0] regRD_i;
assign regRD = regRD_i;
always @ (posedge clk)
begin
if (regRA[7] == HI)
FPGAregister[regRA[(REGLOG2DEPTH-1):0]]:
else
HOSTregister[regRA[(REGLOG2DEPTH-1):0]];
end
// ======================================================================
// HOST Register Write Process
// ----------------------------------------------------------------------
always @ (posedge clk)
begin
if ((regWS == HI) && (regWA[(REGWIDTH-1):REGLOG2DEPTH] == 0) )
HOSTregister[regWA[(REGLOG2DEPTH-1):0]] <= regWD;
else
HOSTregister[regWA[(REGLOG2DEPTH-1):0]] <= HOSTregister[regWA[(REGLOG2DEPTH-1):0]];
end
// ======================================================================
// FPGA Register Write Process
// ----------------------------------------------------------------------
// Write the statically writable inputs to the FPGA registers.
always @ (posedge clk)
begin
FPGAregister[6'h00] <= FR00;
FPGAregister[6'h01] <= FR01;
FPGAregister[6'h02] <= FR02;
FPGAregister[6'h03] <= FR03;
FPGAregister[6'h04] <= FR04;
FPGAregister[6'h05] <= FR05;
FPGAregister[6'h06] <= FR06;
FPGAregister[6'h07] <= FR07;
FPGAregister[6'h08] <= FR08;
FPGAregister[6'h09] <= FR09;
FPGAregister[6'h0A] <= FR0A;
FPGAregister[6'h0B] <= FR0B;
FPGAregister[6'h0C] <= FR0C;
FPGAregister[6'h0D] <= FR0D;
FPGAregister[6'h0E] <= FR0E;
FPGAregister[6'h0F] <= FR0F;
FPGAregister[6'h10] <= FR10;
FPGAregister[6'h11] <= FR11;
FPGAregister[6'h12] <= FR12;
FPGAregister[6'h13] <= FR13;
FPGAregister[6'h14] <= FR14;
FPGAregister[6'h15] <= FR15;
FPGAregister[6'h16] <= FR16;
FPGAregister[6'h17] <= FR17;
FPGAregister[6'h18] <= FR18;
FPGAregister[6'h19] <= FR19;
FPGAregister[6'h1A] <= FR1A;
FPGAregister[6'h1B] <= FR1B;
FPGAregister[6'h1C] <= FR1C;
FPGAregister[6'h1D] <= FR1D;
FPGAregister[6'h1E] <= FR1E;
FPGAregister[6'h1F] <= FR1F;
FPGAregister[6'h20] <= FR20;
FPGAregister[6'h21] <= FR21;
FPGAregister[6'h22] <= FR22;
FPGAregister[6'h23] <= FR23;
FPGAregister[6'h24] <= FR24;
FPGAregister[6'h25] <= FR25;
FPGAregister[6'h26] <= FR26;
FPGAregister[6'h27] <= FR27;
FPGAregister[6'h28] <= FR28;
FPGAregister[6'h29] <= FR29;
FPGAregister[6'h2A] <= FR2A;
FPGAregister[6'h2B] <= FR2B;
FPGAregister[6'h2C] <= FR2C;
FPGAregister[6'h2D] <= FR2D;
FPGAregister[6'h2E] <= FR2E;
FPGAregister[6'h2F] <= FR2F;
FPGAregister[6'h30] <= FR30;
FPGAregister[6'h31] <= FR31;
FPGAregister[6'h32] <= FR32;
FPGAregister[6'h33] <= FR33;
FPGAregister[6'h34] <= FR34;
FPGAregister[6'h35] <= FR35;
FPGAregister[6'h36] <= FR36;
FPGAregister[6'h37] <= FR37;
FPGAregister[6'h38] <= FR38;
FPGAregister[6'h39] <= FR39;
FPGAregister[6'h3A] <= FR3A;
FPGAregister[6'h3B] <= FR3B;
FPGAregister[6'h3C] <= FR3C;
FPGAregister[6'h3D] <= FR3D;
FPGAregister[6'h3E] <= FR3E;
FPGAregister[6'h3F] <= FR3F;
end
// ======================================================================
// HOST Register Map
// ----------------------------------------------------------------------
// Map the HOST registers to the statically readable output ports.
assign HR00 = HOSTregister[6'h00];
assign HR01 = HOSTregister[6'h01];
assign HR02 = HOSTregister[6'h02];
assign HR03 = HOSTregister[6'h03];
assign HR04 = HOSTregister[6'h04];
assign HR05 = HOSTregister[6'h05];
assign HR06 = HOSTregister[6'h06];
assign HR07 = HOSTregister[6'h07];
assign HR08 = HOSTregister[6'h08];
assign HR09 = HOSTregister[6'h09];
assign HR0A = HOSTregister[6'h0A];
assign HR0B = HOSTregister[6'h0B];
assign HR0C = HOSTregister[6'h0C];
assign HR0D = HOSTregister[6'h0D];
assign HR0E = HOSTregister[6'h0E];
assign HR0F = HOSTregister[6'h0F];
assign HR10 = HOSTregister[6'h10];
assign HR11 = HOSTregister[6'h11];
assign HR12 = HOSTregister[6'h12];
assign HR13 = HOSTregister[6'h13];
assign HR14 = HOSTregister[6'h14];
assign HR15 = HOSTregister[6'h15];
assign HR16 = HOSTregister[6'h16];
assign HR17 = HOSTregister[6'h17];
assign HR18 = HOSTregister[6'h18];
assign HR19 = HOSTregister[6'h19];
assign HR1A = HOSTregister[6'h1A];
assign HR1B = HOSTregister[6'h1B];
assign HR1C = HOSTregister[6'h1C];
assign HR1D = HOSTregister[6'h1D];
assign HR1E = HOSTregister[6'h1E];
assign HR1F = HOSTregister[6'h1F];
assign HR20 = HOSTregister[6'h20];
assign HR21 = HOSTregister[6'h21];
assign HR22 = HOSTregister[6'h22];
assign HR23 = HOSTregister[6'h23];
assign HR24 = HOSTregister[6'h24];
assign HR25 = HOSTregister[6'h25];
assign HR26 = HOSTregister[6'h26];
assign HR27 = HOSTregister[6'h27];
assign HR28 = HOSTregister[6'h28];
assign HR29 = HOSTregister[6'h29];
assign HR2A = HOSTregister[6'h2A];
assign HR2B = HOSTregister[6'h2B];
assign HR2C = HOSTregister[6'h2C];
assign HR2D = HOSTregister[6'h2D];
assign HR2E = HOSTregister[6'h2E];
assign HR2F = HOSTregister[6'h2F];
assign HR30 = HOSTregister[6'h30];
assign HR31 = HOSTregister[6'h31];
assign HR32 = HOSTregister[6'h32];
assign HR33 = HOSTregister[6'h33];
assign HR34 = HOSTregister[6'h34];
assign HR35 = HOSTregister[6'h35];
assign HR36 = HOSTregister[6'h36];
assign HR37 = HOSTregister[6'h37];
assign HR38 = HOSTregister[6'h38];
assign HR39 = HOSTregister[6'h39];
assign HR3A = HOSTregister[6'h3A];
assign HR3B = HOSTregister[6'h3B];
assign HR3C = HOSTregister[6'h3C];
assign HR3D = HOSTregister[6'h3D];
assign HR3E = HOSTregister[6'h3E];
assign HR3F = HOSTregister[6'h3F];
endmodule
The following parameter definitions are used throughout the module to make the code more readable and maintainable.
//
======================================================================
// Parameter Definitions
//
----------------------------------------------------------------------
parameter LO = 1'b0, HI = 1'b1; // Logic levels
parameter REGWIDTH = 8;
// Number of bits in each register
parameter REGDEPTH = 64;
// Number of registers in each bank
parameter REGLOG2DEPTH = 6; // Number
of sig bits in register address
Presently, the code is set up to make both register banks the same size, but this can be changed easily. The code is also set up so that each bank's depth is an integral power of two and this can't be changed without significant revisions.
The module's I/O ports are very straightforward. Each HOST register has its output mapped to a separate module output while each FPGA register has its input mapped from a separate module input. The Control Interface is very simple with three ports used to control the updating of the HOST registers and two used to query and the of the registers from either the HOST or the FPGA partition. All data changes are synchronous to the global master clock. Although the global reset is ported into the module (as it is generically into virtually every module), it is not actually used in this module. Hence resetting (as opposed to reconfiguring) the FPGA will have no effect on the contents of the registers.
//
======================================================================
// I/O Port Definitions
//
----------------------------------------------------------------------
// HOST register outputs
output [7:0] HR00, HR01, HR02, HR03, HR04, HR05, HR06, HR07;
output [7:0] HR08, HR09, HR0A, HR0B, HR0C, HR0D, HR0E, HR0F;
output [7:0] HR10, HR11, HR12, HR13, HR14, HR15, HR16, HR17;
output [7:0] HR18, HR19, HR1A, HR1B, HR1C, HR1D, HR1E, HR1F;
output [7:0] HR20, HR21, HR22, HR23, HR24, HR25, HR26, HR27;
output [7:0] HR28, HR29, HR2A, HR2B, HR2C, HR2D, HR2E, HR2F;
output [7:0] HR30, HR31, HR32, HR33, HR34, HR35, HR36, HR37;
output [7:0] HR38, HR39, HR3A, HR3B, HR3C, HR3D, HR3E, HR3F;
// FPGA register inputs
input [7:0] FR00, FR01, FR02, FR03, FR04, FR05, FR06, FR07;
input [7:0] FR08, FR09, FR0A, FR0B, FR0C, FR0D, FR0E, FR0F;
input [7:0] FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17;
input [7:0] FR18, FR19, FR1A, FR1B, FR1C, FR1D, FR1E, FR1F;
input [7:0] FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27;
input [7:0] FR28, FR29, FR2A, FR2B, FR2C, FR2D, FR2E, FR2F;
input [7:0] FR30, FR31, FR32, FR33, FR34, FR35, FR36, FR37;
input [7:0] FR38, FR39, FR3A, FR3B, FR3C, FR3D, FR3E, FR3F;
// Control Interface
input [(REGWIDTH-1):0] regWA; // HOST Register Write
Address
input [(REGWIDTH-1):0] regWD; // HOST Register Write
Data
input
regWS; // HOST Register Write Strobe
input [(REGWIDTH-1):0] regRA; // Register Read Address
output [(REGWIDTH-1):0] regRD; // Register Read Data
// Global reset and clock
input rst, clk;
The following code instantiates two arrays of registers. The first serves as the HOST register space and the second serves as the FPGA register space.
//
======================================================================
// Register Bank Instantiation
//
----------------------------------------------------------------------
// HOST Register Array (written via serial interface)
reg [(REGWIDTH-1):0] HOSTregister[(REGDEPTH-1):0];
// FPGA Register Array (written directly by FPGA)
reg [(REGWIDTH-1):0] FPGAregister[(REGDEPTH-1):0];
To read from the registers, the most significant bit of the
register read address (regRA
) is queried. If it is HI, then
the address is in the upper partition of the register space and the data is
taken from the FPGA registers. If it is LO, then the address is in the lower
partition of the register space and the data is taken from the HOST registers.
If the address maps to an unimplemented register, then it is wrapped back into
the implemented address space for that bank.
//
======================================================================
// FPGA Register Read Process
//
----------------------------------------------------------------------
reg [(REGLOG2DEPTH-1):0] regRD_i;
assign regRD = regRD_i;
always @ (posedge clk)
begin
if (regRA[7]
== HI)
FPGAregister[regRA[(REGLOG2DEPTH-1):0]]:
else
HOSTregister[regRA[(REGLOG2DEPTH-1):0]];
end
To write to the HOST registers, the value of the write strobe (regWS
)
is checked as well as verifying that the write address (regWA
)
lies within the implemented register space. If both tests are met, then the
write data (regWD
) is written into the register on the
rising clock edge, otherwise the present value is maintained.
//
======================================================================
// HOST Register Write Process
//
----------------------------------------------------------------------
always @ (posedge clk)
begin
if ((regWS == HI) && (regWA[(REGWIDTH-1):REGLOG2DEPTH]
== 0) )
HOSTregister[regWA[(REGLOG2DEPTH-1):0]] <= regWD;
else
HOSTregister[regWA[(REGLOG2DEPTH-1):0]] <= HOSTregister[regWA[(REGLOG2DEPTH-1):0]];
end
The FPGA registers are updated on every rising clock edge using the data from the module's input ports.
//
======================================================================
// FPGA Register Write Process
//
----------------------------------------------------------------------
// Write the statically writable inputs to the FPGA
registers.
always @ (posedge clk)
begin
FPGAregister[6'h00] <= FR00;
...
FPGAregister[6'h3F] <= FR3F;
end
The present contents of the HOST registers are applied directly to the module's output ports.
//
======================================================================
// HOST Register Map
//
----------------------------------------------------------------------
// Map the HOST registers to the statically readable output
ports.
assign HR00 = HOSTregister[6'h00];
...
assign HR3F = HOSTregister[6'h3F];