URL
https://opencores.org/ocsvn/wb_lpc/wb_lpc/trunk
Subversion Repositories wb_lpc
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/trunk/rtl/verilog/wb_lpc_defines.v
37,45 → 37,46
|
// Wishbone LPC Master/Slave Interface Definitions |
|
`define LPC_START 4'b0000 |
`define LPC_STOP 4'b1111 |
`define LPC_FW_READ 4'b1101 |
`define LPC_FW_WRITE 4'b1110 |
`define LPC_START 4'b0000 |
`define LPC_STOP 4'b1111 |
`define LPC_FW_READ 4'b1101 |
`define LPC_FW_WRITE 4'b1110 |
|
`define LPC_SYNC_READY 4'b0000 // LPC Sync Ready |
`define LPC_SYNC_SWAIT 4'b0101 // LPC Sync Short Wait |
`define LPC_SYNC_LWAIT 4'b0110 // LPC Sync Long Wait |
`define LPC_SYNC_MORE 4'b1001 // LPC Sync Ready More (DMA only) |
`define LPC_SYNC_ERROR 4'b1010 // LPC Sync Error |
`define LPC_SYNC_READY 4'b0000 // LPC Sync Ready |
`define LPC_SYNC_SWAIT 4'b0101 // LPC Sync Short Wait |
`define LPC_SYNC_LWAIT 4'b0110 // LPC Sync Long Wait |
`define LPC_SYNC_MORE 4'b1001 // LPC Sync Ready More (DMA only) |
`define LPC_SYNC_ERROR 4'b1010 // LPC Sync Error |
|
`define LPC_ST_IDLE 13'h000 // LPC Idle state |
`define LPC_ST_START 13'h001 // LPC Start state |
`define LPC_ST_CYCTYP 13'h002 // LPC Cycle Type State |
`define LPC_ST_ADDR 13'h004 // LPC Address state (4 cycles) |
`define LPC_ST_CHAN 13'h008 // LPC Address state (4 cycles) |
`define LPC_ST_SIZE 13'h010 // LPC Address state (4 cycles) |
`define LPC_ST_H_DATA 13'h020 // LPC Host Data state (2 cycles) |
`define LPC_ST_P_DATA 13'h040 // LPC Peripheral Data state (2 cycles) |
`define LPC_ST_H_TAR1 13'h080 // LPC Host Turnaround 1 (Drive LAD 4'hF) |
`define LPC_ST_H_TAR2 13'h100 // LPC Host Turnaround 2 (Float LAD) |
`define LPC_ST_P_TAR1 13'h200 // LPC Peripheral Turnaround 1 (Drive LAD = 4'hF) |
`define LPC_ST_P_TAR2 13'h400 // LPC Peripheral Turnaround 2 (Float LAD) |
`define LPC_ST_SYNC 13'h800 // LPC Sync State (may be multiple cycles for wait-states) |
`define LPC_ST_P_WAIT1 13'h1000 // LPC Sync State (may be multiple cycles for wait-states) |
`define LPC_ST_IDLE 13'h000 // LPC Idle state |
`define LPC_ST_START 13'h001 // LPC Start state |
`define LPC_ST_CYCTYP 13'h002 // LPC Cycle Type State |
`define LPC_ST_ADDR 13'h004 // LPC Address state (4 cycles) |
`define LPC_ST_CHAN 13'h008 // LPC Address state (4 cycles) |
`define LPC_ST_SIZE 13'h010 // LPC Address state (4 cycles) |
`define LPC_ST_H_DATA 13'h020 // LPC Host Data state (2 cycles) |
`define LPC_ST_P_DATA 13'h040 // LPC Peripheral Data state (2 cycles) |
`define LPC_ST_H_TAR1 13'h080 // LPC Host Turnaround 1 (Drive LAD 4'hF) |
`define LPC_ST_H_TAR2 13'h100 // LPC Host Turnaround 2 (Float LAD) |
`define LPC_ST_P_TAR1 13'h200 // LPC Peripheral Turnaround 1 (Drive LAD = 4'hF) |
`define LPC_ST_P_TAR2 13'h400 // LPC Peripheral Turnaround 2 (Float LAD) |
`define LPC_ST_WB_RETIRE 13'h400 // Retire Wishbone transfer (Host only), ends WB cycle. |
`define LPC_ST_SYNC 13'h800 // LPC Sync State (may be multiple cycles for wait-states) |
`define LPC_ST_P_WAIT1 13'h1000 // LPC Sync State (may be multiple cycles for wait-states) |
|
|
`define WB_SEL_BYTE 4'b0001 // Byte Transfer |
`define WB_SEL_SHORT 4'b0011 // Short Transfer |
`define WB_SEL_WORD 4'b1111 // Word Transfer |
`define WB_SEL_BYTE 4'b0001 // Byte Transfer |
`define WB_SEL_SHORT 4'b0011 // Short Transfer |
`define WB_SEL_WORD 4'b1111 // Word Transfer |
|
`define WB_TGA_MEM 2'b00 // Memory Cycle |
`define WB_TGA_IO 2'b01 // I/O Cycle |
`define WB_TGA_FW 2'b10 // Firmware Cycle |
`define WB_TGA_DMA 2'b11 // DMA Cycle |
`define WB_TGA_MEM 2'b00 // Memory Cycle |
`define WB_TGA_IO 2'b01 // I/O Cycle |
`define WB_TGA_FW 2'b10 // Firmware Cycle |
`define WB_TGA_DMA 2'b11 // DMA Cycle |
|
// LDRQ States |
|
`define LDRQ_ST_IDLE 4'h0 |
`define LDRQ_ST_ADDR 4'h1 |
`define LDRQ_ST_ACT 4'h2 |
`define LDRQ_ST_DONE 4'h4 |
`define LDRQ_ST_IDLE 4'h0 |
`define LDRQ_ST_ADDR 4'h1 |
`define LDRQ_ST_ACT 4'h2 |
`define LDRQ_ST_DONE 4'h4 |
/trunk/rtl/verilog/wb_lpc_host.v
1,6 → 1,6
////////////////////////////////////////////////////////////////////// |
//// //// |
//// $Id: wb_lpc_host.v,v 1.1 2008-03-02 20:46:40 hharte Exp $ |
//// $Id: wb_lpc_host.v,v 1.2 2008-03-05 05:50:25 hharte Exp $ //// |
//// wb_lpc_host.v - Wishbone Slave to LPC Host Bridge //// |
//// //// |
//// This file is part of the Wishbone LPC Bridge project //// |
40,323 → 40,328
|
`include "../../rtl/verilog/wb_lpc_defines.v" |
|
// I/O Write I/O Read DMA Read DMA Write |
// |
// States - 1. H Start H Start H Start H Start |
// 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 |
// H SIZE H SIZE |
// 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+) |
// 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 |
// |
// I/O Write I/O Read DMA Read DMA Write |
// |
// States - 1. H Start H Start H Start H Start |
// 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 |
// H SIZE H SIZE |
// 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+) |
// 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 |
// |
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, |
dma_chan_i, dma_tc_i, |
lframe_o, lad_i, lad_o, lad_oe |
wbs_stb_i, wbs_cyc_i, wbs_ack_o, |
dma_chan_i, dma_tc_i, |
lframe_o, lad_i, lad_o, lad_oe |
); |
// Wishbone Slave Interface |
input clk_i; |
input nrst_i; // Active low reset. |
input [31:0] wbs_adr_i; |
output [31:0] wbs_dat_o; |
input [31:0] wbs_dat_i; |
input [3:0] wbs_sel_i; |
input [1:0] wbs_tga_i; |
input wbs_we_i; |
input wbs_stb_i; |
input wbs_cyc_i; |
output reg wbs_ack_o; |
|
// LPC Master Interface |
output reg lframe_o; // LPC Frame output (active high) |
output reg lad_oe; // LPC AD Output Enable |
input [3:0] lad_i; // LPC AD Input Bus |
output reg [3:0] lad_o; // LPC AD Output Bus |
// Wishbone Slave Interface |
input clk_i; |
input nrst_i; // Active low reset. |
input [31:0] wbs_adr_i; |
output [31:0] wbs_dat_o; |
input [31:0] wbs_dat_i; |
input [3:0] wbs_sel_i; |
input [1:0] wbs_tga_i; |
input wbs_we_i; |
input wbs_stb_i; |
input wbs_cyc_i; |
output reg wbs_ack_o; |
|
// LPC Master Interface |
output reg lframe_o; // LPC Frame output (active high) |
output reg lad_oe; // LPC AD Output Enable |
input [3:0] lad_i; // LPC AD Input Bus |
output reg [3:0] lad_o; // LPC AD Output Bus |
|
// DMA-Specific sideband signals |
input [2:0] dma_chan_i; // DMA Channel |
input dma_tc_i; // DMA Terminal Count |
// DMA-Specific sideband signals |
input [2:0] dma_chan_i; // DMA Channel |
input dma_tc_i; // DMA Terminal Count |
|
reg [12:0] state; // Current state |
reg [2:0] adr_cnt; // Address nibbe counter |
reg [3:0] dat_cnt; // Data nibble counter |
reg [2:0] xfr_len; // Number of nibbls for transfer |
wire [2:0] byte_cnt = dat_cnt[3:1]; // Byte Counter |
wire nibble_cnt = dat_cnt[0]; // Nibble counter |
reg [31:0] lpc_dat_i; // Temporary storage for input word. |
reg [12:0] state; // Current state |
reg [2:0] adr_cnt; // Address nibbe counter |
reg [3:0] dat_cnt; // Data nibble counter |
reg [2:0] xfr_len; // Number of nibbls for transfer |
wire [2:0] byte_cnt = dat_cnt[3:1]; // Byte Counter |
wire nibble_cnt = dat_cnt[0]; // Nibble counter |
reg [31:0] lpc_dat_i; // Temporary storage for input word. |
|
// |
// generate wishbone register signals |
wire wbs_acc = wbs_cyc_i & wbs_stb_i; // Wishbone access |
wire wbs_wr = wbs_acc & wbs_we_i; // Wishbone write access |
// |
// generate wishbone register signals |
wire wbs_acc = wbs_cyc_i & wbs_stb_i; // Wishbone 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. |
wire mem_xfr = (wbs_tga_i == `WB_TGA_MEM); |
wire dma_xfr = (wbs_tga_i == `WB_TGA_DMA); |
wire fw_xfr = (wbs_tga_i == `WB_TGA_FW); |
|
assign wbs_dat_o[31:0] = lpc_dat_i; |
// Memory Cycle (tga== 1'b00) is bit 2=1 for LPC Cycle Type. |
wire mem_xfr = (wbs_tga_i == `WB_TGA_MEM); |
wire dma_xfr = (wbs_tga_i == `WB_TGA_DMA); |
wire fw_xfr = (wbs_tga_i == `WB_TGA_FW); |
|
assign wbs_dat_o[31:0] = lpc_dat_i; |
|
always @(posedge clk_i or negedge nrst_i) |
if(~nrst_i) |
begin |
state <= `LPC_ST_IDLE; |
lframe_o <= 1'b0; |
wbs_ack_o <= 1'b0; |
lad_oe <= 1'b0; |
lad_o <= 4'b0; |
adr_cnt <= 3'b0; |
dat_cnt <= 4'h0; |
xfr_len <= 3'b000; |
lpc_dat_i <= 32'h00000000; |
end |
else begin |
case(state) |
`LPC_ST_IDLE: |
begin |
wbs_ack_o <= 1'b0; |
lframe_o <= 1'b0; |
dat_cnt <= 4'h0; |
always @(posedge clk_i or negedge nrst_i) |
if(~nrst_i) |
begin |
state <= `LPC_ST_IDLE; |
lframe_o <= 1'b0; |
wbs_ack_o <= 1'b0; |
lad_oe <= 1'b0; |
lad_o <= 4'b0; |
adr_cnt <= 3'b0; |
dat_cnt <= 4'h0; |
xfr_len <= 3'b000; |
lpc_dat_i <= 32'h00000000; |
end |
else begin |
case(state) |
`LPC_ST_IDLE: |
begin |
wbs_ack_o <= 1'b0; |
lframe_o <= 1'b0; |
dat_cnt <= 4'h0; |
|
if(wbs_acc) // Wishbone access starts LPC transaction |
state <= `LPC_ST_START; |
else |
state <= `LPC_ST_IDLE; |
end |
`LPC_ST_START: |
begin |
lframe_o <= 1'b1; |
if(~fw_xfr) begin // For Memory and I/O Cycles |
lad_o <= `LPC_START; |
state <= `LPC_ST_CYCTYP; |
end |
else begin // Firmware Read and Write Cycles |
if(wbs_wr) |
lad_o <= `LPC_FW_WRITE; |
else |
lad_o <= `LPC_FW_READ; |
|
state <= `LPC_ST_ADDR; |
end |
lad_oe <= 1'b1; |
adr_cnt <= ((mem_xfr | fw_xfr) ? 3'b000 : 3'b100); |
end |
`LPC_ST_CYCTYP: |
begin |
lframe_o <= 1'b0; |
lad_oe <= 1'b1; |
if(wbs_acc) // Wishbone access starts LPC transaction |
state <= `LPC_ST_START; |
else |
state <= `LPC_ST_IDLE; |
end |
`LPC_ST_START: |
begin |
lframe_o <= 1'b1; |
if(~fw_xfr) begin // For Memory and I/O Cycles |
lad_o <= `LPC_START; |
state <= `LPC_ST_CYCTYP; |
end |
else begin // Firmware Read and Write Cycles |
if(wbs_wr) |
lad_o <= `LPC_FW_WRITE; |
else |
lad_o <= `LPC_FW_READ; |
|
state <= `LPC_ST_ADDR; |
end |
lad_oe <= 1'b1; |
adr_cnt <= ((mem_xfr | fw_xfr) ? 3'b000 : 3'b100); |
end |
`LPC_ST_CYCTYP: |
begin |
lframe_o <= 1'b0; |
lad_oe <= 1'b1; |
|
if(~dma_xfr) |
begin |
lad_o <= {1'b0,mem_xfr,wbs_wr,1'b0}; // Cycle Type/Direction for I/O or MEM |
state <= `LPC_ST_ADDR; |
end |
else // it is DMA |
begin |
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; |
end |
end |
`LPC_ST_ADDR: // Output four nubbles of address. |
begin |
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; |
// however, the most significant nibble is sent first. For firmware and |
// memory cycles, the address is 32-bits. Actually, for memeory accesses, |
// the most significant nibble is known as the IDSEL field. For I/O, |
// the address is only 16-bits wide. |
case(adr_cnt) |
3'h0: |
lad_o <= wbs_adr_i[31:28]; |
3'h1: |
lad_o <= wbs_adr_i[27:24]; |
3'h2: |
lad_o <= wbs_adr_i[23:20]; |
3'h3: |
lad_o <= wbs_adr_i[19:16]; |
3'h4: |
lad_o <= wbs_adr_i[15:12]; |
3'h5: |
lad_o <= wbs_adr_i[11:8]; |
3'h6: |
lad_o <= wbs_adr_i[7:4]; |
3'h7: |
lad_o <= wbs_adr_i[3:0]; |
endcase |
|
adr_cnt <= adr_cnt + 1; |
|
if(adr_cnt == 4'h7) // Last address nibble. |
begin |
if(~fw_xfr) |
if(wbs_wr) |
state <= `LPC_ST_H_DATA; |
else |
state <= `LPC_ST_H_TAR1; |
else // For firmware read/write, we need to transfer the MSIZE nibble |
state <= `LPC_ST_SIZE; |
end |
else |
state <= `LPC_ST_ADDR; |
|
lad_oe <= 1'b1; |
xfr_len <= 3'b001; // One Byte Transfer |
end |
`LPC_ST_CHAN: |
begin |
lad_o <= {dma_tc_i, dma_chan_i}; |
state <= `LPC_ST_SIZE; |
end |
`LPC_ST_SIZE: |
begin |
case(wbs_sel_i) |
`WB_SEL_BYTE: |
begin |
xfr_len <= 3'b001; |
lad_o <= 4'h0; |
end |
`WB_SEL_SHORT: |
begin |
xfr_len <= 3'b010; |
lad_o <= 4'h1; |
end |
`WB_SEL_WORD: |
begin |
xfr_len <= 3'b100; |
if(fw_xfr) // Firmware transfer uses '2' for 4-byte transfer. |
lad_o <= 4'h2; |
else // DMA uses '3' for 4-byte transfer. |
lad_o <= 4'h3; |
end |
default: |
begin |
xfr_len <= 3'b001; |
lad_o <= 4'h0; |
end |
endcase |
if(wbs_wr) |
state <= `LPC_ST_H_DATA; |
else |
state <= `LPC_ST_H_TAR1; |
end |
if(~dma_xfr) |
begin |
lad_o <= {1'b0,mem_xfr,wbs_wr,1'b0}; // Cycle Type/Direction for I/O or MEM |
state <= `LPC_ST_ADDR; |
end |
else // it is DMA |
begin |
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; |
end |
end |
`LPC_ST_ADDR: // Output four nubbles of address. |
begin |
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; |
// however, the most significant nibble is sent first. For firmware and |
// memory cycles, the address is 32-bits. Actually, for memeory accesses, |
// the most significant nibble is known as the IDSEL field. For I/O, |
// the address is only 16-bits wide. |
case(adr_cnt) |
3'h0: |
lad_o <= wbs_adr_i[31:28]; |
3'h1: |
lad_o <= wbs_adr_i[27:24]; |
3'h2: |
lad_o <= wbs_adr_i[23:20]; |
3'h3: |
lad_o <= wbs_adr_i[19:16]; |
3'h4: |
lad_o <= wbs_adr_i[15:12]; |
3'h5: |
lad_o <= wbs_adr_i[11:8]; |
3'h6: |
lad_o <= wbs_adr_i[7:4]; |
3'h7: |
lad_o <= wbs_adr_i[3:0]; |
endcase |
|
adr_cnt <= adr_cnt + 1; |
|
if(adr_cnt == 4'h7) // Last address nibble. |
begin |
if(~fw_xfr) |
if(wbs_wr) |
state <= `LPC_ST_H_DATA; |
else |
state <= `LPC_ST_H_TAR1; |
else // For firmware read/write, we need to transfer the MSIZE nibble |
state <= `LPC_ST_SIZE; |
end |
else |
state <= `LPC_ST_ADDR; |
|
lad_oe <= 1'b1; |
xfr_len <= 3'b001; // One Byte Transfer |
end |
`LPC_ST_CHAN: |
begin |
lad_o <= {dma_tc_i, dma_chan_i}; |
state <= `LPC_ST_SIZE; |
end |
`LPC_ST_SIZE: |
begin |
case(wbs_sel_i) |
`WB_SEL_BYTE: |
begin |
xfr_len <= 3'b001; |
lad_o <= 4'h0; |
end |
`WB_SEL_SHORT: |
begin |
xfr_len <= 3'b010; |
lad_o <= 4'h1; |
end |
`WB_SEL_WORD: |
begin |
xfr_len <= 3'b100; |
if(fw_xfr) // Firmware transfer uses '2' for 4-byte transfer. |
lad_o <= 4'h2; |
else // DMA uses '3' for 4-byte transfer. |
lad_o <= 4'h3; |
end |
default: |
begin |
xfr_len <= 3'b001; |
lad_o <= 4'h0; |
end |
endcase |
if(wbs_wr) |
state <= `LPC_ST_H_DATA; |
else |
state <= `LPC_ST_H_TAR1; |
end |
|
`LPC_ST_H_DATA: |
begin |
lad_oe <= 1'b1; |
case(dat_cnt) // We only support a single byte for I/O. |
4'h0: |
lad_o <= wbs_dat_i[3:0]; |
4'h1: |
lad_o <= wbs_dat_i[7:4]; |
4'h2: |
lad_o <= wbs_dat_i[11:8]; |
4'h3: |
lad_o <= wbs_dat_i[15:12]; |
4'h4: |
lad_o <= wbs_dat_i[19:16]; |
4'h5: |
lad_o <= wbs_dat_i[23:20]; |
4'h6: |
lad_o <= wbs_dat_i[27:24]; |
4'h7: |
lad_o <= wbs_dat_i[31:28]; |
default: |
lad_o <= 4'hx; |
endcase |
|
dat_cnt <= dat_cnt + 1; |
|
if(nibble_cnt == 1'b1) // end of byte |
begin |
state <= `LPC_ST_H_TAR1; |
end |
else |
state <= `LPC_ST_H_DATA; |
end |
|
`LPC_ST_H_TAR1: |
begin |
lad_o <= 4'b1111; // Drive LAD high |
lad_oe <= 1'b1; |
state <= `LPC_ST_H_TAR2; |
end |
`LPC_ST_H_TAR2: |
begin |
lad_oe <= 1'b0; // float LAD |
state <= `LPC_ST_SYNC; |
end |
`LPC_ST_SYNC: |
begin |
lad_oe <= 1'b0; // float LAD |
if(lad_i == `LPC_SYNC_READY) begin |
if(wbs_wr) begin |
state <= `LPC_ST_P_TAR1; |
end |
else |
state <= `LPC_ST_P_DATA; |
end |
else |
state <= `LPC_ST_SYNC; |
end |
|
`LPC_ST_P_DATA: |
begin |
case(dat_cnt) |
4'h0: |
lpc_dat_i[3:0] <= lad_i; |
4'h1: |
lpc_dat_i[7:4] <= lad_i; |
4'h2: |
lpc_dat_i[11:8] <= lad_i; |
4'h3: |
lpc_dat_i[15:12] <= lad_i; |
4'h4: |
lpc_dat_i[19:16] <= lad_i; |
4'h5: |
lpc_dat_i[23:20] <= lad_i; |
4'h6: |
lpc_dat_i[27:24] <= lad_i; |
4'h7: |
lpc_dat_i[31:28] <= lad_i; |
endcase |
|
dat_cnt <= dat_cnt + 1; |
|
if(nibble_cnt == 1'b1) // Byte transfer complete |
if (byte_cnt == xfr_len-1) // End of data transfer phase |
state <= `LPC_ST_P_TAR1; |
else |
state <= `LPC_ST_SYNC; |
else // Go to next nibble |
state <= `LPC_ST_P_DATA; |
end |
`LPC_ST_P_TAR1: |
begin |
lad_oe <= 1'b0; |
// 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; |
wbs_ack_o <= wbs_acc; |
end |
else begin |
if(wbs_wr) begin // DMA READ (Host to Peripheral) |
state <= `LPC_ST_H_DATA; |
end |
else begin // unhandled READ case |
state <= `LPC_ST_IDLE; |
end |
end |
end |
endcase |
end |
`LPC_ST_H_DATA: |
begin |
lad_oe <= 1'b1; |
case(dat_cnt) // We only support a single byte for I/O. |
4'h0: |
lad_o <= wbs_dat_i[3:0]; |
4'h1: |
lad_o <= wbs_dat_i[7:4]; |
4'h2: |
lad_o <= wbs_dat_i[11:8]; |
4'h3: |
lad_o <= wbs_dat_i[15:12]; |
4'h4: |
lad_o <= wbs_dat_i[19:16]; |
4'h5: |
lad_o <= wbs_dat_i[23:20]; |
4'h6: |
lad_o <= wbs_dat_i[27:24]; |
4'h7: |
lad_o <= wbs_dat_i[31:28]; |
default: |
lad_o <= 4'hx; |
endcase |
|
dat_cnt <= dat_cnt + 1; |
|
if(nibble_cnt == 1'b1) // end of byte |
begin |
state <= `LPC_ST_H_TAR1; |
end |
else |
state <= `LPC_ST_H_DATA; |
end |
|
`LPC_ST_H_TAR1: |
begin |
lad_o <= 4'b1111; // Drive LAD high |
lad_oe <= 1'b1; |
state <= `LPC_ST_H_TAR2; |
end |
`LPC_ST_H_TAR2: |
begin |
lad_oe <= 1'b0; // float LAD |
state <= `LPC_ST_SYNC; |
end |
`LPC_ST_SYNC: |
begin |
lad_oe <= 1'b0; // float LAD |
if(lad_i == `LPC_SYNC_READY) begin |
if(wbs_wr) begin |
state <= `LPC_ST_P_TAR1; |
end |
else |
state <= `LPC_ST_P_DATA; |
end |
else |
state <= `LPC_ST_SYNC; |
end |
|
`LPC_ST_P_DATA: |
begin |
case(dat_cnt) |
4'h0: |
lpc_dat_i[3:0] <= lad_i; |
4'h1: |
lpc_dat_i[7:4] <= lad_i; |
4'h2: |
lpc_dat_i[11:8] <= lad_i; |
4'h3: |
lpc_dat_i[15:12] <= lad_i; |
4'h4: |
lpc_dat_i[19:16] <= lad_i; |
4'h5: |
lpc_dat_i[23:20] <= lad_i; |
4'h6: |
lpc_dat_i[27:24] <= lad_i; |
4'h7: |
lpc_dat_i[31:28] <= lad_i; |
endcase |
|
dat_cnt <= dat_cnt + 1; |
|
if(nibble_cnt == 1'b1) // Byte transfer complete |
if (byte_cnt == xfr_len-1) // End of data transfer phase |
state <= `LPC_ST_P_TAR1; |
else |
state <= `LPC_ST_SYNC; |
else // Go to next nibble |
state <= `LPC_ST_P_DATA; |
end |
`LPC_ST_P_TAR1: |
begin |
lad_oe <= 1'b0; |
if(byte_cnt == xfr_len) begin |
state <= `LPC_ST_WB_RETIRE; |
wbs_ack_o <= wbs_acc; |
end |
else begin |
if(wbs_wr) begin // DMA READ (Host to Peripheral) |
state <= `LPC_ST_H_DATA; |
end |
else begin // unhandled READ case |
state <= `LPC_ST_IDLE; |
end |
end |
end |
`LPC_ST_WB_RETIRE: |
begin |
wbs_ack_o <= 1'b0; |
if(wbs_acc) begin |
state <= `LPC_ST_WB_RETIRE; |
end |
else begin |
state <= `LPC_ST_IDLE; |
end |
end |
endcase |
end |
|
endmodule |
|
|
|