hsize = {1'b0, dst_size_limit};
hprot3to1 = dst_prot_ctrl;
end
`PL230_ST_WR_CTRL:
begin
htrans = `PL230_AHB_TRANS_NONSEQ;
hwrite = `PL230_AHB_WRITE;
hsize = `PL230_AHB_SIZE_WORD;
hprot3to1 = chnl_ctrl_hprot3to1;
end
`PL230_ST_RESVD_0,
`PL230_ST_RESVD_1,
`PL230_ST_RESVD_2,
`PL230_ST_RESVD_3,
`PL230_ST_RESVD_4:
begin
htrans = `PL230_AHB_TRANS_IDLE;
hwrite = `PL230_AHB_READ;
hsize = `PL230_AHB_SIZE_WORD;
hprot3to1 = chnl_ctrl_hprot3to1;
end
default:
begin
htrans = 2'bxx;
hwrite = 1'bx;
hsize = 2'bxx;
hprot3to1 = 3'bxxx;
end
endcase
end // p_ahb_ctrl
// AHB interface protection control
// The lsb selects data or opcode fetch
// AHB accesses are always classed as data
assign hprot = {hprot3to1, 1'b1};
// AHB interface burst length
// Only single transactions are supported
assign hburst = 3'b000;
// AHB locked access control
// Locked accesses are not supported
assign hmastlock = 1'b0;
//----------------------------------------------------------------------------
// Address Calculation
//----------------------------------------------------------------------------
// Select source or destination transfer size
// This is done one cycle ahead of the actual AHB address phase
assign mux_size = (ctrl_state == `PL230_ST_RD_SDAT) ? dst_size : src_size;
// Select source or destination address increment
// This is done one cycle ahead of the actual AHB address phase
assign mux_inc = (ctrl_state == `PL230_ST_RD_SDAT) ? dst_inc : src_inc;
// Control for the address offset
always @( mux_size or mux_inc )
begin : p_ctrl_offset
case ( mux_size )
`PL230_SIZE_BYTE:
begin
case ( mux_inc )
2'b00: ctrl_offset = 2'b00;
2'b01: ctrl_offset = 2'b01;
2'b10: ctrl_offset = 2'b10;
2'b11: ctrl_offset = 2'b11;
default: ctrl_offset = 2'bxx;
endcase
end
`PL230_SIZE_HWORD:
begin
case ( mux_inc )
2'b00: ctrl_offset = 2'b01;
2'b01: ctrl_offset = 2'b01;
2'b10: ctrl_offset = 2'b10;
2'b11: ctrl_offset = 2'b11;
default: ctrl_offset = 2'bxx;
endcase
end
`PL230_SIZE_WORD:
begin
case ( mux_inc )
2'b00: ctrl_offset = 2'b10;
2'b01: ctrl_offset = 2'b10;
2'b10: ctrl_offset = 2'b10;
2'b11: ctrl_offset = 2'b11;
default: ctrl_offset = 2'bxx;
endcase
end
`PL230_SIZE_RESVD:
begin
case ( mux_inc )
2'b00: ctrl_offset = 2'b10;
2'b01: ctrl_offset = 2'b10;
2'b10: ctrl_offset = 2'b10;
2'b11: ctrl_offset = 2'b11;
default: ctrl_offset = 2'bxx;
endcase
end
default:
ctrl_offset = 2'bxx;
endcase
end // p_ctrl_offset
// Address offset
always @( ctrl_offset or n_count )
begin : p_addr_offset
case ( ctrl_offset )
2'b00: // Address offset - byte
addr_offset = {2'b00, n_count};
2'b01: // Address offset - halfword
addr_offset = {1'b0, n_count, 1'b0};
2'b10: // Address offset - word
addr_offset = {n_count, 2'b00};
2'b11: // Address offset - fixed address
addr_offset = {`PL230_N_COUNT_BITS+2{1'b0}};
default:
addr_offset = {`PL230_N_COUNT_BITS+2{1'bx}};
endcase
end // p_addr_offset
// Address offset fixed for scatter/gather primary channel
assign addr_offset_sg_pri =
// If using primary control data for scatter gather
(((cycle_ctrl == 3'b100) || (cycle_ctrl == 3'b110)) &&
// and the destination address is being calculated
(ctrl_state == `PL230_ST_RD_SDAT))
// only use two bits of N as the same four alternate control data
// locations must be written to multiple times
? {{`PL230_N_COUNT_BITS-2{1'b0}}, n_count[1:0], 2'b00}
// otherwise use the full address offset
: addr_offset;
// Source/Destination end address
// Lower bits are masked for word and half-word transfers
// to stop the user causing unaligned transfer addresses
always @( mux_size or hrdata )
begin : p_src_dst_end_addr
case ( mux_size )
2'b00:
src_dst_end_addr = hrdata;
2'b01:
src_dst_end_addr = {hrdata[31:1], 1'b0};
2'b10:
src_dst_end_addr = {hrdata[31:2], 2'b00};
2'b11:
src_dst_end_addr = {hrdata[31:2], 2'b00};
default:
src_dst_end_addr = 32'bxxxx_xxxx;
endcase
end // p_src_dst_end_addr
// DMA data address calculation for source and destination
assign dma_addr = src_dst_end_addr -
{{32-`PL230_N_COUNT_BITS-2{1'b0}}, addr_offset_sg_pri};
// Channel control data select
always @( ctrl_state_nxt )
begin : p_ctrl_dat_sel
case (ctrl_state_nxt)
`PL230_ST_RD_CTRL:
ctrl_dat_sel = 2'b10;
`PL230_ST_RD_SPTR:
ctrl_dat_sel = 2'b00;
`PL230_ST_RD_DPTR:
ctrl_dat_sel = 2'b01;
`PL230_ST_WR_CTRL:
ctrl_dat_sel = 2'b10;
`PL230_ST_IDLE,
`PL230_ST_RD_SDAT,
`PL230_ST_WR_DDAT,
`PL230_ST_WAIT,
`PL230_ST_STALL,
`PL230_ST_DONE,
`PL230_ST_PSGP,
`PL230_ST_RESVD_0,
`PL230_ST_RESVD_1,
`PL230_ST_RESVD_2,
`PL230_ST_RESVD_3,
`PL230_ST_RESVD_4:
ctrl_dat_sel = 2'b10;
default:
ctrl_dat_sel = 2'bxx;
endcase
end // p_ctrl_dat_sel
// Channel control data address calculation
assign ctrl_dat_addr = {ctrl_base_ptr,
|(chnl_pri_alt_status & current_chnl_onehot),
`ifdef PL230_ONE_CHNL
`else
current_chnl,
`endif
ctrl_dat_sel,
2'b00};
// AHB interface address next value
assign haddr_nxt = ((data_state == `PL230_ST_RD_SPTR) ||
((data_state == `PL230_ST_RD_DPTR) &&
(cycle_ctrl != 3'b000)))
? dma_addr
: ctrl_dat_addr;
// AHB interface address
always @( negedge hresetn or posedge hclk )
begin : p_haddr
if ( hresetn == 1'b0 )
haddr <= 32'h0000_0000;
else
if ( data_state_en )
haddr <= haddr_nxt;
end // p_haddr
//----------------------------------------------------------------------------
// Two to the power of R counter
//----------------------------------------------------------------------------
// 2^R transfers complete
assign twotor_complete = (twotor_count == {`PL230_N_COUNT_BITS{1'b0}});
// R forced to zero when dma_sreq is the request source
// except for Peripheral Scatter/Gather Primary
assign r_override = ( override_r && (cycle_ctrl != 3'b110) ) ? 4'b0000 : r;
// Power of 2 calculation using R in the channel_cfg register
always @( r_override )
begin : p_twotor
case ( r_override )
4'b0000: twotor = 10'h000;
4'b0001: twotor = 10'h001;
4'b0010: twotor = 10'h003;
4'b0011: twotor = 10'h007;
4'b0100: twotor = 10'h00f;
4'b0101: twotor = 10'h01f;
4'b0110: twotor = 10'h03f;
4'b0111: twotor = 10'h07f;
4'b1000: twotor = 10'h0ff;
4'b1001: twotor = 10'h1ff;
4'b1010,
4'b1011,
4'b1100,
4'b1101,
4'b1110,
4'b1111: twotor = 10'h3ff;
default: twotor = 10'hxxx;
endcase
end // p_twotor
// 2^R counter enable
assign twotor_count_en = twotor_count_load || // Load
(counter_decrement && // Decrement
!twotor_complete);
// 2^R counter load
assign twotor_count_nxt = twotor_count_load
? twotor // Load
: twotor_count - 1; // Decrement
// 2^R counter
always @( negedge hresetn or posedge hclk )
begin : p_twotor_count
if ( hresetn == 1'b0 )
twotor_count <= {`PL230_N_COUNT_BITS{1'b0}};
else
if ( twotor_count_en )
twotor_count <= twotor_count_nxt;
end // p_twotor_count
//----------------------------------------------------------------------------
// N counter
//----------------------------------------------------------------------------
// N transfers complete enable
assign n_complete_en = hready && (data_state == `PL230_ST_RD_SPTR);
// N transfers complete next value
assign n_complete_nxt = (n_count == {`PL230_N_COUNT_BITS{1'b0}});
// N transfers complete
always @( negedge hresetn or posedge hclk )
begin : p_n_complete
if ( hresetn == 1'b0 )
n_complete <= 1'b0;
else
if ( n_complete_en )
n_complete <= n_complete_nxt;
end // p_n_complete
// N counter enable
assign n_count_en = channel_cfg_load || // Load
(counter_decrement && // Decrement
!n_complete && !disable_on_slave_err);
// N counter load
assign n_count_nxt = channel_cfg_load
? hrdata[`PL230_N_COUNT_BITS-1+`PL230_N_COUNT_OFFSET
:`PL230_N_COUNT_OFFSET] // Load
: n_count - 1; // Decrement
// N counter
always @( negedge hresetn or posedge hclk )
begin : p_n_count
if ( hresetn == 1'b0 )
n_count <= {`PL230_N_COUNT_BITS{1'b0}};
else
if ( n_count_en )
n_count <= n_count_nxt;
end // p_n_count
endmodule // pl230_ahb_ctrl
`include "pl230_undefs.v"
This page: |
Created: | Wed Nov 24 14:08:44 2021 |
|
From: |
../../../../../../arm-AAA-ip/DMA-230_MicroDMA_Controller/PL230-BU-00000-r0p0-02rel1/verilog/pl230_ahb_ctrl.v |