// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator // https://github.com/SystemRDL/PeakRDL-regblock module verilog6502_io_regs ( input wire clk, input wire rst, taxi_apb_if.slv s_apb, output verilog6502_io_regs_pkg::verilog6502_io_regs__out_t hwif_out ); //-------------------------------------------------------------------------- // CPU Bus interface logic //-------------------------------------------------------------------------- logic cpuif_req; logic cpuif_req_is_wr; logic [11:0] cpuif_addr; logic [31:0] cpuif_wr_data; logic [31:0] cpuif_wr_biten; logic cpuif_req_stall_wr; logic cpuif_req_stall_rd; logic cpuif_rd_ack; logic cpuif_rd_err; logic [31:0] cpuif_rd_data; logic cpuif_wr_ack; logic cpuif_wr_err; `ifndef SYNTHESIS initial begin assert_bad_addr_width: assert($bits(s_apb.paddr) >= verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_MIN_ADDR_WIDTH) else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits(s_apb.paddr), verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_MIN_ADDR_WIDTH); assert_bad_data_width: assert($bits(s_apb.pwdata) == verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_DATA_WIDTH) else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits(s_apb.pwdata), verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_DATA_WIDTH); end `endif // Request logic is_active; always_ff @(posedge clk) begin if(rst) begin is_active <= '0; cpuif_req <= '0; cpuif_req_is_wr <= '0; cpuif_addr <= '0; cpuif_wr_data <= '0; cpuif_wr_biten <= '0; end else begin if(~is_active) begin if(s_apb.psel) begin is_active <= '1; cpuif_req <= '1; cpuif_req_is_wr <= s_apb.pwrite; cpuif_addr <= {s_apb.paddr[11:2], 2'b0}; cpuif_wr_data <= s_apb.pwdata; for(int i=0; i<4; i++) begin cpuif_wr_biten[i*8 +: 8] <= {8{s_apb.pstrb[i]}}; end end end else begin cpuif_req <= '0; if(cpuif_rd_ack || cpuif_wr_ack) begin is_active <= '0; end end end end // Response assign s_apb.pready = cpuif_rd_ack | cpuif_wr_ack; assign s_apb.prdata = cpuif_rd_data; assign s_apb.pslverr = cpuif_rd_err | cpuif_wr_err; logic cpuif_req_masked; // Read & write latencies are balanced. Stalls not required assign cpuif_req_stall_rd = '0; assign cpuif_req_stall_wr = '0; assign cpuif_req_masked = cpuif_req & !(!cpuif_req_is_wr & cpuif_req_stall_rd) & !(cpuif_req_is_wr & cpuif_req_stall_wr); //-------------------------------------------------------------------------- // Address Decode //-------------------------------------------------------------------------- typedef struct { logic core_ctrl; logic nmi; logic reset_brq; } decoded_reg_strb_t; decoded_reg_strb_t decoded_reg_strb; logic decoded_err; logic [11:0] decoded_addr; logic decoded_req; logic decoded_req_is_wr; logic [31:0] decoded_wr_data; logic [31:0] decoded_wr_biten; always_comb begin automatic logic is_valid_addr; automatic logic is_valid_rw; is_valid_addr = '1; // No valid address check is_valid_rw = '1; // No valid RW check decoded_reg_strb.core_ctrl = cpuif_req_masked & (cpuif_addr == 12'h0); decoded_reg_strb.nmi = cpuif_req_masked & (cpuif_addr == 12'hff8); decoded_reg_strb.reset_brq = cpuif_req_masked & (cpuif_addr == 12'hffc); decoded_err = '0; end // Pass down signals to next stage assign decoded_addr = cpuif_addr; assign decoded_req = cpuif_req_masked; assign decoded_req_is_wr = cpuif_req_is_wr; assign decoded_wr_data = cpuif_wr_data; assign decoded_wr_biten = cpuif_wr_biten; //-------------------------------------------------------------------------- // Field logic //-------------------------------------------------------------------------- typedef struct { struct { struct { logic next; logic load_next; } reset; } core_ctrl; struct { struct { logic [15:0] next; logic load_next; } nmi; } nmi; struct { struct { logic [15:0] next; logic load_next; } reset; struct { logic [15:0] next; logic load_next; } brk; } reset_brq; } field_combo_t; field_combo_t field_combo; typedef struct { struct { struct { logic value; } reset; } core_ctrl; struct { struct { logic [15:0] value; } nmi; } nmi; struct { struct { logic [15:0] value; } reset; struct { logic [15:0] value; } brk; } reset_brq; } field_storage_t; field_storage_t field_storage; // Field: verilog6502_io_regs.core_ctrl.reset always_comb begin automatic logic [0:0] next_c; automatic logic load_next_c; next_c = field_storage.core_ctrl.reset.value; load_next_c = '0; if(decoded_reg_strb.core_ctrl && decoded_req_is_wr) begin // SW write next_c = (field_storage.core_ctrl.reset.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); load_next_c = '1; end field_combo.core_ctrl.reset.next = next_c; field_combo.core_ctrl.reset.load_next = load_next_c; end always_ff @(posedge clk) begin if(rst) begin field_storage.core_ctrl.reset.value <= 1'h1; end else begin if(field_combo.core_ctrl.reset.load_next) begin field_storage.core_ctrl.reset.value <= field_combo.core_ctrl.reset.next; end end end assign hwif_out.core_ctrl.reset.value = field_storage.core_ctrl.reset.value; // Field: verilog6502_io_regs.nmi.nmi always_comb begin automatic logic [15:0] next_c; automatic logic load_next_c; next_c = field_storage.nmi.nmi.value; load_next_c = '0; if(decoded_reg_strb.nmi && decoded_req_is_wr) begin // SW write next_c = (field_storage.nmi.nmi.value & ~decoded_wr_biten[31:16]) | (decoded_wr_data[31:16] & decoded_wr_biten[31:16]); load_next_c = '1; end field_combo.nmi.nmi.next = next_c; field_combo.nmi.nmi.load_next = load_next_c; end always_ff @(posedge clk) begin if(rst) begin field_storage.nmi.nmi.value <= 16'h200; end else begin if(field_combo.nmi.nmi.load_next) begin field_storage.nmi.nmi.value <= field_combo.nmi.nmi.next; end end end assign hwif_out.nmi.nmi.value = field_storage.nmi.nmi.value; // Field: verilog6502_io_regs.reset_brq.reset always_comb begin automatic logic [15:0] next_c; automatic logic load_next_c; next_c = field_storage.reset_brq.reset.value; load_next_c = '0; if(decoded_reg_strb.reset_brq && decoded_req_is_wr) begin // SW write next_c = (field_storage.reset_brq.reset.value & ~decoded_wr_biten[15:0]) | (decoded_wr_data[15:0] & decoded_wr_biten[15:0]); load_next_c = '1; end field_combo.reset_brq.reset.next = next_c; field_combo.reset_brq.reset.load_next = load_next_c; end always_ff @(posedge clk) begin if(rst) begin field_storage.reset_brq.reset.value <= 16'h200; end else begin if(field_combo.reset_brq.reset.load_next) begin field_storage.reset_brq.reset.value <= field_combo.reset_brq.reset.next; end end end assign hwif_out.reset_brq.reset.value = field_storage.reset_brq.reset.value; // Field: verilog6502_io_regs.reset_brq.brk always_comb begin automatic logic [15:0] next_c; automatic logic load_next_c; next_c = field_storage.reset_brq.brk.value; load_next_c = '0; if(decoded_reg_strb.reset_brq && decoded_req_is_wr) begin // SW write next_c = (field_storage.reset_brq.brk.value & ~decoded_wr_biten[31:16]) | (decoded_wr_data[31:16] & decoded_wr_biten[31:16]); load_next_c = '1; end field_combo.reset_brq.brk.next = next_c; field_combo.reset_brq.brk.load_next = load_next_c; end always_ff @(posedge clk) begin if(rst) begin field_storage.reset_brq.brk.value <= 16'h200; end else begin if(field_combo.reset_brq.brk.load_next) begin field_storage.reset_brq.brk.value <= field_combo.reset_brq.brk.next; end end end assign hwif_out.reset_brq.brk.value = field_storage.reset_brq.brk.value; //-------------------------------------------------------------------------- // Write response //-------------------------------------------------------------------------- assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; // Writes are always granted with no error response assign cpuif_wr_err = '0; //-------------------------------------------------------------------------- // Readback //-------------------------------------------------------------------------- logic [11:0] rd_mux_addr; assign rd_mux_addr = decoded_addr; logic readback_err; logic readback_done; logic [31:0] readback_data; always_comb begin automatic logic [31:0] readback_data_var; readback_data_var = '0; if(rd_mux_addr == 12'h0) begin readback_data_var[0] = field_storage.core_ctrl.reset.value; end if(rd_mux_addr == 12'hff8) begin readback_data_var[31:16] = field_storage.nmi.nmi.value; end if(rd_mux_addr == 12'hffc) begin readback_data_var[15:0] = field_storage.reset_brq.reset.value; readback_data_var[31:16] = field_storage.reset_brq.brk.value; end readback_data = readback_data_var; readback_done = decoded_req & ~decoded_req_is_wr; readback_err = '0; end assign cpuif_rd_ack = readback_done; assign cpuif_rd_data = readback_data; assign cpuif_rd_err = readback_err; endmodule