# example for csrGen.pl script # First, specify overall parameters for our design: # %B is the block name, used in the module declaration and file names %B example_lp # %C allows us to name the clock, default would be "clock" %C clk # %RST allows us to name the low true reset, default would be "initl" %RST reset_l # (The script is just a single clock and single reset for now) # %WD is to specify the data bus that write data should be taken from # in our example, up_dinQ is a flopped copy of the processor bus pins %WD up_dinQ # %RD similarly is a name for the read data bus - used in read case statement %RD up_dout_D %REV $Id: example.csrs,v 1.2 2004/08/03 20:14:56 cbenz Exp cbenz $ # Now, aside from the register case statements which are done automatically, # this script has you prepare the surrounding logic yourself. So you specify # those IOs and flops. %I is input, %F is a flop, and %OF is a flopped output. %I up_din # The %F takes the 2nd param as the width, 3rd as reset value, and 4th as # a direct logic input. All are optional, default logic input would be # name_D (auto declared if using default), default reset value is 0, default # width is 1. %F up_dinQ 8 0 up_din # %I also allows a width %I up_addr 4 %I up_csl %I up_rwl %F up_addrQ 4 0 up_addr %F up_cslQ 1 0 up_csl %F up_cslQQ 1 0 up_cslQ %F up_rwlQ 1 0 up_rwl %OF up_dout 8 %OF up_dout_ENL 1 1 (up_cslQ|up_rwlQ) # Now specify register contents - open each address as %A and give address. # RO in our first example makes the register a readonly address. # Then we declare each field, starting with bit position(s) and name. # Each field can have options - "intern" means that the field is not an IO # to the logic, it's wholly within this module. %A 0 "a simple version register" RO "more doc text" # use reset value as complement of operational constant value # to force flops to be used, so ECOs can easily be made 3:0 version intern "da version" "more about the version field" 7:4 deviceID intern %V `define chip_version 0 `define chip_deviceID 1 `define chip_version_bar ~ `chip_version `define chip_deviceID_bar ~ `chip_deviceID %E %F version 4 `chip_version_bar `chip_version %F deviceID 4 `chip_deviceID_bar `chip_deviceID # default usage is that a field is read/write and becomes an output of # our module. %A 1 7:0 control1 # If a field spans several addresses, we use the SUB/SUBM contstruct %A 2 7:0 control2 SUB 7:0 %A 3 3:0 control2 SUBM 11:8 # a read-only field becomes an input to our module (unless declared intern) %A 4 5:0 status1 ro # ST is a special sticky form of read only - a sticky memory of the input # is kept, and can be cleared when the register is read (COR), or by # writing a 1 to the field. %A 5 7 stickybit1 ST COR 6 stickybit2 ST w1c %AREPEAT 6 2 7 repeatingfield 6 morerepeat buss %E # Now the VCL (verilog combinational logic) construct is where we put # the logic together. Everything between %VCL and %E will be put within # an "always @ (...) begin" / end block. Within %VCL, the %readcase and # %writecase will be expanded with the case statements for reads and # writes of the registers. # The logic here is simple processor logic - the leading assertion of # up_csl causes the read or write, and a tristate enable allows the read # data to continue until csl is deasserted. %VCL up_dout_D = 0 ; if (up_cslQQ & ! up_cslQ & up_rwlQ) case (up_addrQ) %readcase endcase if (up_cslQQ & ! up_cslQ & ! up_rwlQ) case (up_addrQ) %writecase endcase %E # and a final %E completes the file %E