//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// $Id: wb_lpc_host.v,v 1.4 2008-07-26 19:15:31 hharte Exp $ ////
|
//// $Id: wb_lpc_host.v,v 1.4 2008-07-26 19:15:31 hharte Exp $ ////
|
//// wb_lpc_host.v - Wishbone Slave to LPC Host Bridge ////
|
//// wb_lpc_host.v - Wishbone Slave to LPC Host Bridge ////
|
//// ////
|
//// ////
|
//// This file is part of the Wishbone LPC Bridge project ////
|
//// This file is part of the Wishbone LPC Bridge project ////
|
//// http://www.opencores.org/projects/wb_lpc/ ////
|
//// http://www.opencores.org/projects/wb_lpc/ ////
|
//// ////
|
//// ////
|
//// Author: ////
|
//// Author: ////
|
//// - Howard M. Harte (hharte@opencores.org) ////
|
//// - Howard M. Harte (hharte@opencores.org) ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2008 Howard M. Harte ////
|
//// Copyright (C) 2008 Howard M. Harte ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
`timescale 1 ns / 1 ns
|
`timescale 1 ns / 1 ns
|
|
|
`include "../../rtl/verilog/wb_lpc_defines.v"
|
`include "../../rtl/verilog/wb_lpc_defines.v"
|
|
|
// I/O Write I/O Read DMA Read DMA Write
|
// I/O Write I/O Read DMA Read DMA Write
|
//
|
//
|
// States - 1. H Start H Start H Start H Start
|
// States - 1. H Start H Start H Start H Start
|
// 2. H CYCTYPE+DIR H CYCTYPE+DIR H CYCTYPE+DIR H CYCTYPE+DIR
|
// 2. H CYCTYPE+DIR H CYCTYPE+DIR H CYCTYPE+DIR H CYCTYPE+DIR
|
// 3. H Addr (4) H Addr (4) H CHAN+TC H CHAN+TC
|
// 3. H Addr (4) H Addr (4) H CHAN+TC H CHAN+TC
|
// H SIZE H SIZE
|
// H SIZE H SIZE
|
// 4. H Data (2) H TAR (2) +-H DATA (2) H TAR (2)
|
// 4. H Data (2) H TAR (2) +-H DATA (2) H TAR (2)
|
// 5. H TAR (2) P SYNC (1+) | H TAR (2) +-P SYNC (1+)
|
// 5. H TAR (2) P SYNC (1+) | H TAR (2) +-P SYNC (1+)
|
// 6. P SYNC (1+) P DATA (2) | H SYNC (1+) +-P DATA (2)
|
// 6. P SYNC (1+) P DATA (2) | H SYNC (1+) +-P DATA (2)
|
// 7. P TAR (2) P TAR (2) +-P TAR (2) P TAR
|
// 7. P TAR (2) P TAR (2) +-P TAR (2) P TAR
|
//
|
//
|
module wb_lpc_host(clk_i, nrst_i, wbs_adr_i, wbs_dat_o, wbs_dat_i, wbs_sel_i, wbs_tga_i, wbs_we_i,
|
module wb_lpc_host(clk_i, nrst_i, wbs_adr_i, wbs_dat_o, wbs_dat_i, wbs_sel_i, wbs_tga_i, wbs_we_i,
|
wbs_stb_i, wbs_cyc_i, wbs_ack_o, wbs_err_o,
|
wbs_stb_i, wbs_cyc_i, wbs_ack_o, wbs_err_o,
|
dma_chan_i, dma_tc_i,
|
dma_chan_i, dma_tc_i,
|
lframe_o, lad_i, lad_o, lad_oe
|
lframe_o, lad_i, lad_o, lad_oe
|
);
|
);
|
// Wishbone Slave Interface
|
// Wishbone Slave Interface
|
input clk_i;
|
input clk_i;
|
input nrst_i; // Active low reset.
|
input nrst_i; // Active low reset.
|
input [31:0] wbs_adr_i;
|
input [31:0] wbs_adr_i;
|
output [31:0] wbs_dat_o;
|
output [31:0] wbs_dat_o;
|
input [31:0] wbs_dat_i;
|
input [31:0] wbs_dat_i;
|
input [3:0] wbs_sel_i;
|
input [3:0] wbs_sel_i;
|
input [1:0] wbs_tga_i;
|
input [1:0] wbs_tga_i;
|
input wbs_we_i;
|
input wbs_we_i;
|
input wbs_stb_i;
|
input wbs_stb_i;
|
input wbs_cyc_i;
|
input wbs_cyc_i;
|
output reg wbs_ack_o;
|
output reg wbs_ack_o;
|
output reg wbs_err_o;
|
output reg wbs_err_o;
|
|
|
// LPC Master Interface
|
// LPC Master Interface
|
output reg lframe_o; // LPC Frame output (active high)
|
output reg lframe_o; // LPC Frame output (active high)
|
output reg lad_oe; // LPC AD Output Enable
|
output reg lad_oe; // LPC AD Output Enable
|
input [3:0] lad_i; // LPC AD Input Bus
|
input [3:0] lad_i; // LPC AD Input Bus
|
output reg [3:0] lad_o; // LPC AD Output Bus
|
output reg [3:0] lad_o; // LPC AD Output Bus
|
|
|
// DMA-Specific sideband signals
|
// DMA-Specific sideband signals
|
input [2:0] dma_chan_i; // DMA Channel
|
input [2:0] dma_chan_i; // DMA Channel
|
input dma_tc_i; // DMA Terminal Count
|
input dma_tc_i; // DMA Terminal Count
|
|
|
reg [13:0] state; // Current state
|
reg [13:0] state; // Current state
|
reg [2:0] adr_cnt; // Address nibbe counter
|
reg [2:0] adr_cnt; // Address nibbe counter
|
reg [3:0] dat_cnt; // Data nibble counter
|
reg [3:0] dat_cnt; // Data nibble counter
|
reg [2:0] xfr_len; // Number of nibbls for transfer
|
reg [2:0] xfr_len; // Number of nibbls for transfer
|
wire [2:0] byte_cnt = dat_cnt[3:1]; // Byte Counter
|
wire [2:0] byte_cnt = dat_cnt[3:1]; // Byte Counter
|
wire nibble_cnt = dat_cnt[0]; // Nibble counter
|
wire nibble_cnt = dat_cnt[0]; // Nibble counter
|
reg [31:0] lpc_dat_i; // Temporary storage for input word.
|
reg [31:0] lpc_dat_i; // Temporary storage for input word.
|
|
|
//
|
//
|
// generate wishbone register signals
|
// generate wishbone register signals
|
wire wbs_acc = wbs_cyc_i & wbs_stb_i; // Wishbone access
|
wire wbs_acc = wbs_cyc_i & wbs_stb_i; // Wishbone access
|
wire wbs_wr = wbs_acc & wbs_we_i; // Wishbone write access
|
wire wbs_wr = wbs_acc & wbs_we_i; // Wishbone write access
|
|
|
// Memory Cycle (tga== 1'b00) is bit 2=1 for LPC Cycle Type.
|
// Memory Cycle (tga== 1'b00) is bit 2=1 for LPC Cycle Type.
|
wire mem_xfr = (wbs_tga_i == `WB_TGA_MEM);
|
wire mem_xfr = (wbs_tga_i == `WB_TGA_MEM);
|
wire dma_xfr = (wbs_tga_i == `WB_TGA_DMA);
|
wire dma_xfr = (wbs_tga_i == `WB_TGA_DMA);
|
wire fw_xfr = (wbs_tga_i == `WB_TGA_FW);
|
wire fw_xfr = (wbs_tga_i == `WB_TGA_FW);
|
|
|
assign wbs_dat_o[31:0] = lpc_dat_i;
|
assign wbs_dat_o[31:0] = lpc_dat_i;
|
|
|
always @(posedge clk_i or negedge nrst_i)
|
always @(posedge clk_i or negedge nrst_i)
|
if(~nrst_i)
|
if(~nrst_i)
|
begin
|
begin
|
state <= `LPC_ST_IDLE;
|
state <= `LPC_ST_IDLE;
|
lframe_o <= 1'b0;
|
lframe_o <= 1'b0;
|
wbs_ack_o <= 1'b0;
|
wbs_ack_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
lad_oe <= 1'b0;
|
lad_oe <= 1'b0;
|
lad_o <= 4'b0;
|
lad_o <= 4'b0;
|
adr_cnt <= 3'b0;
|
adr_cnt <= 3'b0;
|
dat_cnt <= 4'h0;
|
dat_cnt <= 4'h0;
|
xfr_len <= 3'b000;
|
xfr_len <= 3'b000;
|
lpc_dat_i <= 32'h00000000;
|
lpc_dat_i <= 32'h00000000;
|
end
|
end
|
else begin
|
else begin
|
case(state)
|
case(state)
|
`LPC_ST_IDLE:
|
`LPC_ST_IDLE:
|
begin
|
begin
|
wbs_ack_o <= 1'b0;
|
wbs_ack_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
lframe_o <= 1'b0;
|
lframe_o <= 1'b0;
|
dat_cnt <= 4'h0;
|
dat_cnt <= 4'h0;
|
|
|
if(wbs_acc) // Wishbone access starts LPC transaction
|
if(wbs_acc) // Wishbone access starts LPC transaction
|
state <= `LPC_ST_START;
|
state <= `LPC_ST_START;
|
else
|
else
|
state <= `LPC_ST_IDLE;
|
state <= `LPC_ST_IDLE;
|
end
|
end
|
`LPC_ST_START:
|
`LPC_ST_START:
|
begin
|
begin
|
lframe_o <= 1'b1;
|
lframe_o <= 1'b1;
|
if(~fw_xfr) begin // For Memory and I/O Cycles
|
if(~fw_xfr) begin // For Memory and I/O Cycles
|
lad_o <= `LPC_START;
|
lad_o <= `LPC_START;
|
state <= `LPC_ST_CYCTYP;
|
state <= `LPC_ST_CYCTYP;
|
end
|
end
|
else begin // Firmware Read and Write Cycles
|
else begin // Firmware Read and Write Cycles
|
if(wbs_wr)
|
if(wbs_wr)
|
lad_o <= `LPC_FW_WRITE;
|
lad_o <= `LPC_FW_WRITE;
|
else
|
else
|
lad_o <= `LPC_FW_READ;
|
lad_o <= `LPC_FW_READ;
|
|
|
state <= `LPC_ST_ADDR;
|
state <= `LPC_ST_ADDR;
|
end
|
end
|
lad_oe <= 1'b1;
|
lad_oe <= 1'b1;
|
adr_cnt <= ((mem_xfr | fw_xfr) ? 3'b000 : 3'b100);
|
adr_cnt <= ((mem_xfr | fw_xfr) ? 3'b000 : 3'b100);
|
end
|
end
|
`LPC_ST_CYCTYP:
|
`LPC_ST_CYCTYP:
|
begin
|
begin
|
lframe_o <= 1'b0;
|
lframe_o <= 1'b0;
|
lad_oe <= 1'b1;
|
lad_oe <= 1'b1;
|
|
|
if(~dma_xfr)
|
if(~dma_xfr)
|
begin
|
begin
|
lad_o <= {1'b0,mem_xfr,wbs_wr,1'b0}; // Cycle Type/Direction for I/O or MEM
|
lad_o <= {1'b0,mem_xfr,wbs_wr,1'b0}; // Cycle Type/Direction for I/O or MEM
|
state <= `LPC_ST_ADDR;
|
state <= `LPC_ST_ADDR;
|
end
|
end
|
else // it is DMA
|
else // it is DMA
|
begin
|
begin
|
lad_o <= {1'b1,1'b0,~wbs_wr,1'b0}; // Cycle Type/Direction for DMA, r/w is inverted for DMA
|
lad_o <= {1'b1,1'b0,~wbs_wr,1'b0}; // Cycle Type/Direction for DMA, r/w is inverted for DMA
|
state <= `LPC_ST_CHAN;
|
state <= `LPC_ST_CHAN;
|
end
|
end
|
end
|
end
|
`LPC_ST_ADDR: // Output four nubbles of address.
|
`LPC_ST_ADDR: // Output four nubbles of address.
|
begin
|
begin
|
lframe_o <= 1'b0; // In case we came here from a Firmware cycle, which skips CYCTYP.
|
lframe_o <= 1'b0; // In case we came here from a Firmware cycle, which skips CYCTYP.
|
|
|
// The LPC Bus Address is sent across the bus a nibble at a time;
|
// The LPC Bus Address is sent across the bus a nibble at a time;
|
// however, the most significant nibble is sent first. For firmware and
|
// however, the most significant nibble is sent first. For firmware and
|
// memory cycles, the address is 32-bits. Actually, for firmware accesses,
|
// memory cycles, the address is 32-bits. Actually, for firmware accesses,
|
// the most significant nibble is known as the IDSEL field. For I/O,
|
// the most significant nibble is known as the IDSEL field. For I/O,
|
// the address is only 16-bits wide.
|
// the address is only 16-bits wide.
|
case(adr_cnt)
|
case(adr_cnt)
|
3'h0:
|
3'h0:
|
lad_o <= wbs_adr_i[31:28];
|
lad_o <= wbs_adr_i[31:28];
|
3'h1:
|
3'h1:
|
lad_o <= wbs_adr_i[27:24];
|
lad_o <= wbs_adr_i[27:24];
|
3'h2:
|
3'h2:
|
lad_o <= wbs_adr_i[23:20];
|
lad_o <= wbs_adr_i[23:20];
|
3'h3:
|
3'h3:
|
lad_o <= wbs_adr_i[19:16];
|
lad_o <= wbs_adr_i[19:16];
|
3'h4:
|
3'h4:
|
lad_o <= wbs_adr_i[15:12];
|
lad_o <= wbs_adr_i[15:12];
|
3'h5:
|
3'h5:
|
lad_o <= wbs_adr_i[11:8];
|
lad_o <= wbs_adr_i[11:8];
|
3'h6:
|
3'h6:
|
lad_o <= wbs_adr_i[7:4];
|
lad_o <= wbs_adr_i[7:4];
|
3'h7:
|
3'h7:
|
lad_o <= wbs_adr_i[3:0];
|
lad_o <= wbs_adr_i[3:0];
|
endcase
|
endcase
|
|
|
adr_cnt <= adr_cnt + 1;
|
adr_cnt <= adr_cnt + 1;
|
|
|
if(adr_cnt == 4'h7) // Last address nibble.
|
if(adr_cnt == 4'h7) // Last address nibble.
|
begin
|
begin
|
if(~fw_xfr)
|
if(~fw_xfr)
|
if(wbs_wr)
|
if(wbs_wr)
|
state <= `LPC_ST_H_DATA;
|
state <= `LPC_ST_H_DATA;
|
else
|
else
|
state <= `LPC_ST_H_TAR1;
|
state <= `LPC_ST_H_TAR1;
|
else // For firmware read/write, we need to transfer the MSIZE nibble
|
else // For firmware read/write, we need to transfer the MSIZE nibble
|
state <= `LPC_ST_SIZE;
|
state <= `LPC_ST_SIZE;
|
end
|
end
|
else
|
else
|
state <= `LPC_ST_ADDR;
|
state <= `LPC_ST_ADDR;
|
|
|
lad_oe <= 1'b1;
|
lad_oe <= 1'b1;
|
xfr_len <= 3'b001; // One Byte Transfer
|
xfr_len <= 3'b001; // One Byte Transfer
|
end
|
end
|
`LPC_ST_CHAN:
|
`LPC_ST_CHAN:
|
begin
|
begin
|
lad_o <= {dma_tc_i, dma_chan_i};
|
lad_o <= {dma_tc_i, dma_chan_i};
|
state <= `LPC_ST_SIZE;
|
state <= `LPC_ST_SIZE;
|
end
|
end
|
`LPC_ST_SIZE:
|
`LPC_ST_SIZE:
|
begin
|
begin
|
case(wbs_sel_i)
|
case(wbs_sel_i)
|
`WB_SEL_BYTE:
|
`WB_SEL_BYTE:
|
begin
|
begin
|
xfr_len <= 3'b001;
|
xfr_len <= 3'b001;
|
lad_o <= 4'h0;
|
lad_o <= 4'h0;
|
end
|
end
|
`WB_SEL_SHORT:
|
`WB_SEL_SHORT:
|
begin
|
begin
|
xfr_len <= 3'b010;
|
xfr_len <= 3'b010;
|
lad_o <= 4'h1;
|
lad_o <= 4'h1;
|
end
|
end
|
`WB_SEL_WORD:
|
`WB_SEL_WORD:
|
begin
|
begin
|
xfr_len <= 3'b100;
|
xfr_len <= 3'b100;
|
if(fw_xfr) // Firmware transfer uses '2' for 4-byte transfer.
|
if(fw_xfr) // Firmware transfer uses '2' for 4-byte transfer.
|
lad_o <= 4'h2;
|
lad_o <= 4'h2;
|
else // DMA uses '3' for 4-byte transfer.
|
else // DMA uses '3' for 4-byte transfer.
|
lad_o <= 4'h3;
|
lad_o <= 4'h3;
|
end
|
end
|
default:
|
default:
|
begin
|
begin
|
xfr_len <= 3'b001;
|
xfr_len <= 3'b001;
|
lad_o <= 4'h0;
|
lad_o <= 4'h0;
|
end
|
end
|
endcase
|
endcase
|
if(wbs_wr)
|
if(wbs_wr)
|
state <= `LPC_ST_H_DATA;
|
state <= `LPC_ST_H_DATA;
|
else
|
else
|
state <= `LPC_ST_H_TAR1;
|
state <= `LPC_ST_H_TAR1;
|
end
|
end
|
|
|
`LPC_ST_H_DATA:
|
`LPC_ST_H_DATA:
|
begin
|
begin
|
lad_oe <= 1'b1;
|
lad_oe <= 1'b1;
|
case(dat_cnt) // We only support a single byte for I/O.
|
case(dat_cnt) // We only support a single byte for I/O.
|
4'h0:
|
4'h0:
|
lad_o <= wbs_dat_i[3:0];
|
lad_o <= wbs_dat_i[3:0];
|
4'h1:
|
4'h1:
|
lad_o <= wbs_dat_i[7:4];
|
lad_o <= wbs_dat_i[7:4];
|
4'h2:
|
4'h2:
|
lad_o <= wbs_dat_i[11:8];
|
lad_o <= wbs_dat_i[11:8];
|
4'h3:
|
4'h3:
|
lad_o <= wbs_dat_i[15:12];
|
lad_o <= wbs_dat_i[15:12];
|
4'h4:
|
4'h4:
|
lad_o <= wbs_dat_i[19:16];
|
lad_o <= wbs_dat_i[19:16];
|
4'h5:
|
4'h5:
|
lad_o <= wbs_dat_i[23:20];
|
lad_o <= wbs_dat_i[23:20];
|
4'h6:
|
4'h6:
|
lad_o <= wbs_dat_i[27:24];
|
lad_o <= wbs_dat_i[27:24];
|
4'h7:
|
4'h7:
|
lad_o <= wbs_dat_i[31:28];
|
lad_o <= wbs_dat_i[31:28];
|
default:
|
default:
|
lad_o <= 4'hx;
|
lad_o <= 4'hx;
|
endcase
|
endcase
|
|
|
dat_cnt <= dat_cnt + 1;
|
dat_cnt <= dat_cnt + 1;
|
|
|
if(nibble_cnt == 1'b1) // end of byte
|
if(nibble_cnt == 1'b1) // end of byte
|
begin
|
begin
|
if((fw_xfr) && (byte_cnt != xfr_len-1)) // Firmware transfer does not have TAR between bytes.
|
if((fw_xfr) && (byte_cnt != xfr_len-1)) // Firmware transfer does not have TAR between bytes.
|
state <= `LPC_ST_H_DATA;
|
state <= `LPC_ST_H_DATA;
|
else
|
else
|
state <= `LPC_ST_H_TAR1;
|
state <= `LPC_ST_H_TAR1;
|
end
|
end
|
else
|
else
|
state <= `LPC_ST_H_DATA;
|
state <= `LPC_ST_H_DATA;
|
end
|
end
|
|
|
`LPC_ST_H_TAR1:
|
`LPC_ST_H_TAR1:
|
begin
|
begin
|
lad_o <= 4'b1111; // Drive LAD high
|
lad_o <= 4'b1111; // Drive LAD high
|
lad_oe <= 1'b1;
|
lad_oe <= 1'b1;
|
state <= `LPC_ST_H_TAR2;
|
state <= `LPC_ST_H_TAR2;
|
end
|
end
|
`LPC_ST_H_TAR2:
|
`LPC_ST_H_TAR2:
|
begin
|
begin
|
lad_oe <= 1'b0; // float LAD
|
lad_oe <= 1'b0; // float LAD
|
state <= `LPC_ST_SYNC;
|
state <= `LPC_ST_SYNC;
|
end
|
end
|
`LPC_ST_SYNC:
|
`LPC_ST_SYNC:
|
begin
|
begin
|
lad_oe <= 1'b0; // float LAD
|
lad_oe <= 1'b0; // float LAD
|
if((lad_i == `LPC_SYNC_READY) || (lad_i == `LPC_SYNC_MORE)) begin
|
if((lad_i == `LPC_SYNC_READY) || (lad_i == `LPC_SYNC_MORE)) begin
|
if(wbs_wr) begin
|
if(wbs_wr) begin
|
state <= `LPC_ST_P_TAR1;
|
state <= `LPC_ST_P_TAR1;
|
end
|
end
|
else begin
|
else begin
|
state <= `LPC_ST_P_DATA;
|
state <= `LPC_ST_P_DATA;
|
end
|
end
|
end else if(lad_i == `LPC_SYNC_ERROR) begin
|
end else if(lad_i == `LPC_SYNC_ERROR) begin
|
dat_cnt <= { xfr_len, 1'b1 }; // Terminate data transfer
|
dat_cnt <= { xfr_len, 1'b1 }; // Terminate data transfer
|
wbs_err_o <= 1'b1; // signal wishbone error
|
wbs_err_o <= 1'b1; // signal wishbone error
|
state <= `LPC_ST_P_TAR1;
|
state <= `LPC_ST_P_TAR1;
|
end else begin
|
end else begin
|
state <= `LPC_ST_SYNC;
|
state <= `LPC_ST_SYNC;
|
end
|
end
|
end
|
end
|
|
|
`LPC_ST_P_DATA:
|
`LPC_ST_P_DATA:
|
begin
|
begin
|
case(dat_cnt)
|
case(dat_cnt)
|
4'h0:
|
4'h0:
|
lpc_dat_i[3:0] <= lad_i;
|
lpc_dat_i[3:0] <= lad_i;
|
4'h1:
|
4'h1:
|
lpc_dat_i[7:4] <= lad_i;
|
lpc_dat_i[7:4] <= lad_i;
|
4'h2:
|
4'h2:
|
lpc_dat_i[11:8] <= lad_i;
|
lpc_dat_i[11:8] <= lad_i;
|
4'h3:
|
4'h3:
|
lpc_dat_i[15:12] <= lad_i;
|
lpc_dat_i[15:12] <= lad_i;
|
4'h4:
|
4'h4:
|
lpc_dat_i[19:16] <= lad_i;
|
lpc_dat_i[19:16] <= lad_i;
|
4'h5:
|
4'h5:
|
lpc_dat_i[23:20] <= lad_i;
|
lpc_dat_i[23:20] <= lad_i;
|
4'h6:
|
4'h6:
|
lpc_dat_i[27:24] <= lad_i;
|
lpc_dat_i[27:24] <= lad_i;
|
4'h7:
|
4'h7:
|
lpc_dat_i[31:28] <= lad_i;
|
lpc_dat_i[31:28] <= lad_i;
|
endcase
|
endcase
|
|
|
dat_cnt <= dat_cnt + 1;
|
dat_cnt <= dat_cnt + 1;
|
|
|
if(nibble_cnt == 1'b1) // Byte transfer complete
|
if(nibble_cnt == 1'b1) // Byte transfer complete
|
if (byte_cnt == xfr_len-1) // End of data transfer phase
|
if (byte_cnt == xfr_len-1) // End of data transfer phase
|
state <= `LPC_ST_P_TAR1;
|
state <= `LPC_ST_P_TAR1;
|
else begin
|
else begin
|
if(fw_xfr) // Firmware transfer does not have TAR between bytes.
|
if(fw_xfr) // Firmware transfer does not have TAR between bytes.
|
state <= `LPC_ST_P_DATA;
|
state <= `LPC_ST_P_DATA;
|
else
|
else
|
state <= `LPC_ST_SYNC;
|
state <= `LPC_ST_SYNC;
|
end
|
end
|
else // Go to next nibble
|
else // Go to next nibble
|
state <= `LPC_ST_P_DATA;
|
state <= `LPC_ST_P_DATA;
|
end
|
end
|
`LPC_ST_P_TAR1:
|
`LPC_ST_P_TAR1:
|
begin
|
begin
|
lad_oe <= 1'b0;
|
lad_oe <= 1'b0;
|
if(byte_cnt == xfr_len) begin
|
if(byte_cnt == xfr_len) begin
|
state <= `LPC_ST_WB_RETIRE;
|
state <= `LPC_ST_WB_RETIRE;
|
wbs_ack_o <= wbs_acc;
|
wbs_ack_o <= wbs_acc;
|
end
|
end
|
else begin
|
else begin
|
if(wbs_wr) begin // DMA READ (Host to Peripheral)
|
if(wbs_wr) begin // DMA READ (Host to Peripheral)
|
state <= `LPC_ST_H_DATA;
|
state <= `LPC_ST_H_DATA;
|
end
|
end
|
else begin // unhandled READ case
|
else begin // unhandled READ case
|
state <= `LPC_ST_IDLE;
|
state <= `LPC_ST_IDLE;
|
end
|
end
|
end
|
end
|
end
|
end
|
`LPC_ST_WB_RETIRE:
|
`LPC_ST_WB_RETIRE:
|
begin
|
begin
|
wbs_ack_o <= 1'b0;
|
wbs_ack_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
wbs_err_o <= 1'b0;
|
if(wbs_acc) begin
|
if(wbs_acc) begin
|
state <= `LPC_ST_WB_RETIRE;
|
state <= `LPC_ST_WB_RETIRE;
|
end
|
end
|
else begin
|
else begin
|
state <= `LPC_ST_IDLE;
|
state <= `LPC_ST_IDLE;
|
end
|
end
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|