URL
https://opencores.org/ocsvn/hive/hive/trunk
Subversion Repositories hive
[/] [hive/] [trunk/] [v04.05/] [reg_base.v] - Rev 4
Compare with Previous | Blame | View Log
/* -------------------------------------------------------------------------------- Module: reg_base.v Function: - Single base processor register w/ multiple type & input options (synchronous). Instantiates: - Nothing. Notes: - Init value for each latched bit. - LIVE_MASK[i]=1 indicates live bit. - LIVE_MASK[i]=0 indicates dead bit, reads zero. - Optional resync (2x registering) of inputs. - Optional edge detection (rising) of inputs. - rd_data_o is driven non-zero if there is an address match, regardless of state of rd_i. - Use large OR gate to combine multiple register set read data. OUT_MODE: - "ZERO" : zero out - "THRU" : no latch, direct connect - "LTCH" : write latch - "LOOP" : no latch, output selected read data READ_MODE: - "THRU" : no latch, direct connect - "CORD" : set on input one, clear on read - "COW1" : set on input one, clear on write one - "DFFE" : D type flip flop with enable - "LOOP" : no latch, read selected output data -------------------------------------------------------------------------------- */ module reg_base #( parameter integer DATA_W = 8, // data width (bits) parameter integer ADDR_W = 4, // address width (bits) parameter [ADDR_W-1:0] ADDRESS = 0, // address this register responds to parameter OUT_MODE = "LOOP", // modes are: "ZERO", "THRU", "LTCH", "LOOP" parameter READ_MODE = "COW1", // modes are: "THRU", "CORD", "COW1", "DFFE", "LOOP" parameter [DATA_W-1:0] LIVE_MASK = { DATA_W{ 1'b1 } }, // 1=live data bit, 0=dead (0) parameter IN_RESYNC = 0, // 1=resync (double clock) input, 0=no resync parameter IN_EDGE = 0, // 1=edge (rising) sensitive, 0=level sensitive parameter [DATA_W-1:0] RESET_VAL = 0 // reset value of latched data ) ( // clocks & resets input wire clk_i, // clock input wire rst_i, // async. reset, active high // bus interface input wire [ADDR_W-1:0] addr_i, // address input wire wr_i, // data write enable, active high input wire rd_i, // data read enable, active high input wire [DATA_W-1:0] wr_data_i, // write data output wire [DATA_W-1:0] rd_data_o, // read data // register interface output wire reg_wr_o, // reg write active, active high output wire reg_rd_o, // reg read active, active high input wire reg_en_i, // reg enable, active high ("DFFE" mode only) input wire [DATA_W-1:0] reg_data_i, // reg data in output wire [DATA_W-1:0] reg_data_o // reg data out ); /* ---------------------- -- internal signals -- ---------------------- */ wire addr_match; genvar i; wire [DATA_W-1:0] in_data, out_data, rd_data; /* ================ == code start == ================ */ // check for address match assign addr_match = ( addr_i == ADDRESS[ADDR_W-1:0] ); // decode read & write assign reg_rd_o = ( rd_i & addr_match ); assign reg_wr_o = ( wr_i & addr_match ); // generate output logic based on mode generate for ( i=0; i<DATA_W; i=i+1 ) begin : output_loop if ( LIVE_MASK[i] ) begin // live bit case ( OUT_MODE ) "ZERO" : begin assign out_data[i] = 1'b0; end "THRU" : begin assign out_data[i] = wr_data_i[i]; end "LTCH" : begin reg reg_bit; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin reg_bit <= RESET_VAL[i]; end else begin if ( reg_wr_o ) begin reg_bit <= wr_data_i[i]; end end end assign out_data[i] = reg_bit; end "LOOP" : begin assign out_data[i] = rd_data[i]; end default : begin // unknown mode! initial $display ( "OUT_MODE %s does not exist!", OUT_MODE ); end endcase end else begin // dead bit assign out_data[i] = 1'b0; end end endgenerate // generate optional input resync & edge detect logic generate for ( i=0; i<DATA_W; i=i+1 ) begin : input_processing_loop if ( LIVE_MASK[i] ) begin // live bit wire in_2; if ( IN_RESYNC ) begin reg in_0, in_1; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin in_0 <= 1'b0; in_1 <= 1'b0; end else begin in_0 <= reg_data_i[i]; in_1 <= in_0; end end assign in_2 = in_1; end else begin assign in_2 = reg_data_i[i]; end // if ( IN_EDGE ) begin reg in_3; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin in_3 <= 1'b0; end else begin in_3 <= in_2; end end assign in_data[i] = ( in_2 & ~in_3 ); end else begin assign in_data[i] = in_2; end end else begin // dead bit assign in_data[i] = 1'b0; end // endif end // endfor endgenerate // generate read logic based on mode generate for ( i=0; i<DATA_W; i=i+1 ) begin : read_loop if ( LIVE_MASK[i] ) begin // live bit case ( READ_MODE ) "THRU" : begin assign rd_data[i] = in_data[i]; end "CORD" : begin reg reg_bit; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin reg_bit <= RESET_VAL[i]; end else begin if ( reg_rd_o ) begin reg_bit <= 1'b0; end else begin reg_bit <= reg_bit | in_data[i]; end end end assign rd_data[i] = reg_bit; end "COW1" : begin reg reg_bit; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin reg_bit <= RESET_VAL[i]; end else begin if ( reg_wr_o ) begin reg_bit <= reg_bit & ~wr_data_i[i]; end else begin reg_bit <= reg_bit | in_data[i]; end end end assign rd_data[i] = reg_bit; end "DFFE" : begin reg reg_bit; always @ ( posedge clk_i or posedge rst_i ) begin if ( rst_i ) begin reg_bit <= RESET_VAL[i]; end else if ( reg_en_i ) begin reg_bit <= in_data[i]; end end assign rd_data[i] = reg_bit; end "LOOP" : begin assign rd_data[i] = out_data[i]; end default : begin // unknown mode! initial $display ( "RD_MODE %s does not exist!", RD_MODE ); end endcase end else begin // dead bit assign rd_data[i] = 1'b0; end end endgenerate // drive outputs assign rd_data_o = ( addr_match ) ? rd_data : 1'b0; assign reg_data_o = out_data; endmodule