📄 wb_lpc_periph.v
字号:
state <= `LPC_ST_SIZE; end `LPC_ST_SIZE: begin case(lad_i) 4'h0: xfr_len <= 3'b001; 4'h1: xfr_len <= 3'b010; 4'h2: xfr_len <= 3'b100; // Firmware transfer uses '2' for 4-byte transfer. 4'h3: xfr_len <= 3'b100; // DMA uses '3' for 4-byte transfer. default: xfr_len <= 3'b001; endcase if(lpc_write) state <= `LPC_ST_H_DATA; else state <= `LPC_ST_H_TAR1; end `LPC_ST_H_DATA: begin case(dat_cnt) 4'h0: lpc_dat_o[ 3: 0] <= lad_i; 4'h1: lpc_dat_o[ 7: 4] <= lad_i; 4'h2: lpc_dat_o[11: 8] <= lad_i; 4'h3: lpc_dat_o[15:12] <= lad_i; 4'h4: lpc_dat_o[19:16] <= lad_i; 4'h5: lpc_dat_o[23:20] <= lad_i; 4'h6: lpc_dat_o[27:24] <= lad_i; 4'h7: lpc_dat_o[31:28] <= lad_i; endcase dat_cnt <= dat_cnt + 1; if(nibble_cnt == 1'b1) // end of byte begin if((fw_xfr) && (byte_cnt != xfr_len-1)) // Firmware transfer does not have TAR between bytes. state <= `LPC_ST_H_DATA; else state <= `LPC_ST_H_TAR1; end else state <= `LPC_ST_H_DATA; end `LPC_ST_H_TAR1: begin // It is ok to start the Wishbone Cycle, done below... state <= `LPC_ST_H_TAR2; end `LPC_ST_H_TAR2: begin state <= (fw_xfr & lpc_write) ? `LPC_ST_FWW_SYNC : `LPC_ST_SYNC; lad_o <= (fw_xfr & lpc_write) ? `LPC_SYNC_READY : `LPC_SYNC_SWAIT; lad_oe <= 1'b1; // start driving LAD end `LPC_ST_SYNC: begin lad_oe <= 1'b1; // start driving LAD // First byte of WB read, last byte of WB write if(((byte_cnt == xfr_len) & lpc_write) | ((byte_cnt == 0) & ~lpc_write)) begin // Errors can not be signalled for Firmware Memory accesses according to the spec. if((wbm_err_i) && (~fw_xfr)) begin dat_cnt <= { xfr_len, 1'b1 }; // Abort remainder of transfer lad_o <= `LPC_SYNC_ERROR; // Bus error state <= `LPC_ST_P_TAR1; end else if(got_ack) begin if(lpc_write) begin lad_o <= `LPC_SYNC_READY; // Ready state <= `LPC_ST_P_TAR1; end else begin // READY+MORE for multi-byte DMA, except the final byte. // For non-DMA cycles, only READY lad_o <= (((xfr_len == 1) & ~lpc_write) || (~dma_xfr)) ? `LPC_SYNC_READY : `LPC_SYNC_MORE; state <= `LPC_ST_P_DATA; end end else begin state <= `LPC_ST_SYNC; lad_o <= `LPC_SYNC_SWAIT; end end else begin // Multi-byte transfer, just ack right away. if(lpc_write) begin lad_o <= (dma_xfr) ? `LPC_SYNC_MORE : `LPC_SYNC_READY; state <= `LPC_ST_P_TAR1; end else begin lad_o <= ((byte_cnt == xfr_len-1) || (~dma_xfr)) ? `LPC_SYNC_READY : `LPC_SYNC_MORE; // Ready-More state <= `LPC_ST_P_DATA; end end end `LPC_ST_FWW_SYNC: // Firmware write requires a special SYNC without wait-states. begin lad_o <= 4'hF; state <= `LPC_ST_P_TAR2; end `LPC_ST_P_DATA: begin case(dat_cnt) 4'h0: lad_o <= lpc_dat_i[ 3: 0]; 4'h1: lad_o <= lpc_dat_i[ 7: 4]; 4'h2: lad_o <= lpc_dat_i[11: 8]; 4'h3: lad_o <= lpc_dat_i[15:12]; 4'h4: lad_o <= lpc_dat_i[19:16]; 4'h5: lad_o <= lpc_dat_i[23:20]; 4'h6: lad_o <= lpc_dat_i[27:24]; 4'h7: lad_o <= lpc_dat_i[31:28]; endcase dat_cnt <= dat_cnt + 1; if(nibble_cnt == 1'b1) // Byte transfer complete if (byte_cnt == xfr_len-1) // Byte transfer complete state <= `LPC_ST_P_TAR1; else begin if(fw_xfr) // Firmware transfer does not have TAR between bytes. state <= `LPC_ST_P_DATA; else state <= `LPC_ST_SYNC; end else state <= `LPC_ST_P_DATA; lad_oe <= 1'b1; end `LPC_ST_P_TAR1: begin lad_oe <= 1'b1; lad_o <= 4'hF; state <= `LPC_ST_P_TAR2; end `LPC_ST_P_TAR2: begin lad_oe <= 1'b0; // float LAD if(byte_cnt == xfr_len) begin state <= `LPC_ST_IDLE; end else begin if(lpc_write) begin // DMA READ (Host to Peripheral) state <= `LPC_ST_P_WAIT1; end else begin // unhandled READ case state <= `LPC_ST_IDLE; end end end `LPC_ST_P_WAIT1: state <= `LPC_ST_H_DATA; endcase end// The goal here is to split the Wishbone cycle handling out of the main state-machine// so it can run independently. This is needed so that in the case of a firmware write,// where the FLASH requires wait-states (which are not allowed for FW write according to// the LPC Specification.) In this case, since the FLASH cannot insert wait-states,// a subsequent LPC operation (which must not be another FW Write) will insert wait-// states before starting the next Wishbone master cycle.//// The only reason that I can think of for the LPC spec to mandate that Firmware Writes// must not insert wait-states is that since FLASH writes can take a very long time,// the LPC spec disallowed them to force LPC FLASH programming software to use polling// to determine when the write is complete rather than inserting a bunch of wait-states,// which would use up too much LPC bus bandwidth, and block other requests from getting// through.// if(~nrst_i) begin wbm_adr_o <= 32'h00000000; wbm_dat_o <= 32'h00000000; wbm_stb_o <= 1'b0; wbm_cyc_o <= 1'b0; wbm_we_o <= 1'b0; wbm_sel_o <= 4'b0000; wbm_tga_o <= `WB_TGA_MEM; got_ack <= 1'b0; end else begin if ((state == `LPC_ST_H_TAR1) && (((byte_cnt == xfr_len) & lpc_write) | ((byte_cnt == 0) & ~lpc_write))) begin // Start Wishbone Cycle wbm_stb_o <= 1'b1; wbm_cyc_o <= 1'b1; wbm_adr_o <= lpc_adr_reg; wbm_dat_o <= lpc_dat_o; wbm_we_o <= lpc_write; wbm_tga_o <= lpc_tga_o; got_ack <= 1'b0; case(xfr_len) 3'h0: wbm_sel_o <= `WB_SEL_BYTE; 3'h2: wbm_sel_o <= `WB_SEL_SHORT; 3'h4: wbm_sel_o <= `WB_SEL_WORD; endcase end else if((wbm_stb_o == 1'b1) && (wbm_ack_i == 1'b1)) begin // End Wishbone Cycle wbm_stb_o <= 1'b0; wbm_cyc_o <= 1'b0; wbm_we_o <= 1'b0; got_ack <= 1'b1; if(~wbm_we_o) begin lpc_dat_i <= wbm_dat_i; end end end endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -