301 lines
11 KiB
Systemverilog
301 lines
11 KiB
Systemverilog
// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
|
|
// https://github.com/SystemRDL/PeakRDL-regblock
|
|
|
|
module {{ds.module_name}}
|
|
{%- if module_has_parameters() %} #(
|
|
{{get_module_parameter_list()|indent(8)}}
|
|
) {%- endif %} (
|
|
{{get_module_port_list()|indent(8)}}
|
|
);
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CPU Bus interface logic
|
|
//--------------------------------------------------------------------------
|
|
logic cpuif_req;
|
|
logic cpuif_req_is_wr;
|
|
logic [{{cpuif.addr_width-1}}:0] cpuif_addr;
|
|
logic [{{cpuif.data_width-1}}:0] cpuif_wr_data;
|
|
logic [{{cpuif.data_width-1}}:0] cpuif_wr_biten;
|
|
logic cpuif_req_stall_wr;
|
|
logic cpuif_req_stall_rd;
|
|
|
|
logic cpuif_rd_ack;
|
|
logic cpuif_rd_err;
|
|
logic [{{cpuif.data_width-1}}:0] cpuif_rd_data;
|
|
|
|
logic cpuif_wr_ack;
|
|
logic cpuif_wr_err;
|
|
|
|
{{cpuif.get_implementation()|indent}}
|
|
|
|
logic cpuif_req_masked;
|
|
{%- if ds.has_external_addressable %}
|
|
logic external_req;
|
|
logic external_pending;
|
|
logic external_wr_ack;
|
|
logic external_rd_ack;
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
external_pending <= '0;
|
|
end else begin
|
|
if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
|
|
else if(external_wr_ack | external_rd_ack) external_pending <= '0;
|
|
`ifndef SYNTHESIS
|
|
assert_bad_ext_wr_ack: assert(!external_wr_ack || (external_pending | external_req))
|
|
else $error("An external wr_ack strobe was asserted when no external request was active");
|
|
assert_bad_ext_rd_ack: assert(!external_rd_ack || (external_pending | external_req))
|
|
else $error("An external rd_ack strobe was asserted when no external request was active");
|
|
`endif
|
|
end
|
|
end
|
|
{%- endif %}
|
|
{% if ds.min_read_latency == ds.min_write_latency %}
|
|
// Read & write latencies are balanced. Stalls not required
|
|
{%- if ds.has_external_addressable %}
|
|
// except if external
|
|
assign cpuif_req_stall_rd = external_pending;
|
|
assign cpuif_req_stall_wr = external_pending;
|
|
{%- else %}
|
|
assign cpuif_req_stall_rd = '0;
|
|
assign cpuif_req_stall_wr = '0;
|
|
{%- endif %}
|
|
{%- elif ds.min_read_latency > ds.min_write_latency %}
|
|
// Read latency > write latency. May need to delay next write that follows a read
|
|
logic [{{ds.min_read_latency - ds.min_write_latency - 1}}:0] cpuif_req_stall_sr;
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
cpuif_req_stall_sr <= '0;
|
|
end else if(cpuif_req && !cpuif_req_is_wr) begin
|
|
cpuif_req_stall_sr <= '1;
|
|
end else begin
|
|
cpuif_req_stall_sr <= (cpuif_req_stall_sr >> 'd1);
|
|
end
|
|
end
|
|
{%- if ds.has_external_addressable %}
|
|
assign cpuif_req_stall_rd = external_pending;
|
|
assign cpuif_req_stall_wr = cpuif_req_stall_sr[0] | external_pending;
|
|
{%- else %}
|
|
assign cpuif_req_stall_rd = '0;
|
|
assign cpuif_req_stall_wr = cpuif_req_stall_sr[0];
|
|
{%- endif %}
|
|
{%- else %}
|
|
// Write latency > read latency. May need to delay next read that follows a write
|
|
logic [{{ds.min_write_latency - ds.min_read_latency - 1}}:0] cpuif_req_stall_sr;
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
cpuif_req_stall_sr <= '0;
|
|
end else if(cpuif_req && cpuif_req_is_wr) begin
|
|
cpuif_req_stall_sr <= '1;
|
|
end else begin
|
|
cpuif_req_stall_sr <= (cpuif_req_stall_sr >> 'd1);
|
|
end
|
|
end
|
|
{%- if ds.has_external_addressable %}
|
|
assign cpuif_req_stall_rd = cpuif_req_stall_sr[0] | external_pending;
|
|
assign cpuif_req_stall_wr = external_pending;
|
|
{%- else %}
|
|
assign cpuif_req_stall_rd = cpuif_req_stall_sr[0];
|
|
assign cpuif_req_stall_wr = '0;
|
|
{%- endif %}
|
|
{%- endif %}
|
|
assign cpuif_req_masked = cpuif_req
|
|
& !(!cpuif_req_is_wr & cpuif_req_stall_rd)
|
|
& !(cpuif_req_is_wr & cpuif_req_stall_wr);
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Address Decode
|
|
//--------------------------------------------------------------------------
|
|
{{address_decode.get_strobe_struct()|indent}}
|
|
decoded_reg_strb_t decoded_reg_strb;
|
|
logic decoded_err;
|
|
{%- if ds.has_external_addressable %}
|
|
logic decoded_strb_is_external;
|
|
{% endif %}
|
|
{%- if ds.has_external_block %}
|
|
logic [{{cpuif.addr_width-1}}:0] decoded_addr;
|
|
{% endif %}
|
|
logic decoded_req;
|
|
logic decoded_req_is_wr;
|
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_data;
|
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_biten;
|
|
|
|
always_comb begin
|
|
automatic logic is_valid_addr;
|
|
automatic logic is_valid_rw;
|
|
{%- if ds.has_external_addressable %}
|
|
automatic logic is_external;
|
|
is_external = '0;
|
|
{%- endif %}
|
|
{%- if ds.err_if_bad_addr or ds.err_if_bad_rw %}
|
|
is_valid_addr = '0;
|
|
{%- else %}
|
|
is_valid_addr = '1; // No valid address check
|
|
{%- endif %}
|
|
{%- if ds.err_if_bad_rw %}
|
|
is_valid_rw = '0;
|
|
{%- else %}
|
|
is_valid_rw = '1; // No valid RW check
|
|
{%- endif %}
|
|
{{address_decode.get_implementation()|indent(8)}}
|
|
{%- if ds.err_if_bad_addr and ds.err_if_bad_rw %}
|
|
decoded_err = (~is_valid_addr | (is_valid_addr & ~is_valid_rw)) & decoded_req;
|
|
{%- elif ds.err_if_bad_addr %}
|
|
decoded_err = ~is_valid_addr & decoded_req;
|
|
{%- elif ds.err_if_bad_rw %}
|
|
decoded_err = (is_valid_addr & ~is_valid_rw) & decoded_req;
|
|
{%- else %}
|
|
decoded_err = '0;
|
|
{%- endif %}
|
|
{%- if ds.has_external_addressable %}
|
|
decoded_strb_is_external = is_external;
|
|
external_req = is_external;
|
|
{%- endif %}
|
|
end
|
|
|
|
// Pass down signals to next stage
|
|
{%- if ds.has_external_block %}
|
|
assign decoded_addr = cpuif_addr;
|
|
{% endif %}
|
|
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;
|
|
{% if ds.has_writable_msb0_fields %}
|
|
// bitswap for use by fields with msb0 ordering
|
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_data_bswap;
|
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_biten_bswap;
|
|
assign decoded_wr_data_bswap = {<<{decoded_wr_data}};
|
|
assign decoded_wr_biten_bswap = {<<{decoded_wr_biten}};
|
|
{%- endif %}
|
|
|
|
{%- if ds.has_buffered_write_regs %}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Write double-buffers
|
|
//--------------------------------------------------------------------------
|
|
{{write_buffering.get_storage_struct()|indent}}
|
|
|
|
{{write_buffering.get_implementation()|indent}}
|
|
{%- endif %}
|
|
//--------------------------------------------------------------------------
|
|
// Field logic
|
|
//--------------------------------------------------------------------------
|
|
{{field_logic.get_combo_struct()|indent}}
|
|
|
|
{{field_logic.get_storage_struct()|indent}}
|
|
|
|
{{field_logic.get_implementation()|indent}}
|
|
|
|
{%- if ds.has_paritycheck %}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Parity Error
|
|
//--------------------------------------------------------------------------
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
parity_error <= '0;
|
|
end else begin
|
|
automatic logic err;
|
|
err = '0;
|
|
{{parity.get_implementation()|indent(12)}}
|
|
parity_error <= err;
|
|
end
|
|
end
|
|
{%- endif %}
|
|
|
|
{%- if ds.has_buffered_read_regs %}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Read double-buffers
|
|
//--------------------------------------------------------------------------
|
|
{{read_buffering.get_storage_struct()|indent}}
|
|
|
|
{{read_buffering.get_implementation()|indent}}
|
|
{%- endif %}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Write response
|
|
//--------------------------------------------------------------------------
|
|
{%- if ds.has_external_addressable %}
|
|
always_comb begin
|
|
automatic logic wr_ack;
|
|
wr_ack = '0;
|
|
{{ext_write_acks.get_implementation()|indent(8)}}
|
|
external_wr_ack = wr_ack;
|
|
end
|
|
assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
|
|
{%- else %}
|
|
assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
|
|
{%- endif %}
|
|
// Writes are always granted with no error response
|
|
{%- if ds.err_if_bad_addr or ds.err_if_bad_rw %}
|
|
assign cpuif_wr_err = decoded_err;
|
|
{%- else %}
|
|
assign cpuif_wr_err = '0;
|
|
{%- endif %}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Readback
|
|
//--------------------------------------------------------------------------
|
|
{%- if ds.has_external_addressable %}
|
|
logic readback_external_rd_ack_c;
|
|
always_comb begin
|
|
automatic logic rd_ack;
|
|
rd_ack = '0;
|
|
{{ext_read_acks.get_implementation()|indent(8)}}
|
|
readback_external_rd_ack_c = rd_ack;
|
|
end
|
|
|
|
logic readback_external_rd_ack;
|
|
{%- if ds.retime_read_fanin %}
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
readback_external_rd_ack <= '0;
|
|
end else begin
|
|
readback_external_rd_ack <= readback_external_rd_ack_c;
|
|
end
|
|
end
|
|
|
|
{%- else %}
|
|
|
|
assign readback_external_rd_ack = readback_external_rd_ack_c;
|
|
{%- endif %}
|
|
{%- endif %}
|
|
|
|
logic readback_err;
|
|
logic readback_done;
|
|
logic [{{cpuif.data_width-1}}:0] readback_data;
|
|
{{readback_implementation|indent}}
|
|
{% if ds.retime_read_response %}
|
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
|
if({{get_resetsignal(cpuif.reset)}}) begin
|
|
cpuif_rd_ack <= '0;
|
|
cpuif_rd_data <= '0;
|
|
cpuif_rd_err <= '0;
|
|
{%- if ds.has_external_addressable %}
|
|
external_rd_ack <= '0;
|
|
{%- endif %}
|
|
end else begin
|
|
{%- if ds.has_external_addressable %}
|
|
external_rd_ack <= readback_external_rd_ack;
|
|
cpuif_rd_ack <= readback_done | readback_external_rd_ack;
|
|
{%- else %}
|
|
cpuif_rd_ack <= readback_done;
|
|
{%- endif %}
|
|
cpuif_rd_data <= readback_data;
|
|
cpuif_rd_err <= readback_err;
|
|
end
|
|
end
|
|
{% else %}
|
|
{%- if ds.has_external_addressable %}
|
|
assign external_rd_ack = readback_external_rd_ack;
|
|
assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
|
|
{%- else %}
|
|
assign cpuif_rd_ack = readback_done;
|
|
{%- endif %}
|
|
assign cpuif_rd_data = readback_data;
|
|
assign cpuif_rd_err = readback_err;
|
|
{%- endif %}
|
|
endmodule
|
|
{# (eof newline anchor) #}
|