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
/wb_lpc/trunk/rtl/verilog
- from Rev 19 to Rev 20
- ↔ Reverse comparison
Rev 19 → Rev 20
/serirq_slave.v
0,0 → 1,200
////////////////////////////////////////////////////////////////////// |
//// //// |
//// $Id: serirq_slave.v,v 1.2 2008-12-27 19:46:18 hharte Exp $ //// |
//// serirq_slave.v - Wishbone Slave to SERIRQ Host Bridge //// |
//// //// |
//// This file is part of the Wishbone LPC Bridge project //// |
//// http://www.opencores.org/projects/lpc/ //// |
//// //// |
//// Author: //// |
//// - Howard M. Harte (hharte@opencores.org) //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2008 Howard M. Harte //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
`timescale 1 ns / 1 ns |
|
`include "../../rtl/verilog/serirq_defines.v" |
|
module serirq_slave(clk_i, nrst_i, |
irq_i, |
serirq_o, serirq_i, serirq_oe |
); |
// Wishbone Slave Interface |
input clk_i; |
input nrst_i; // Active low reset. |
|
// SERIRQ Master Interface |
output reg serirq_o; // SERIRQ output |
input serirq_i; // SERIRQ Input |
output reg serirq_oe; // SERIRQ Output Enable |
|
input [31:0] irq_i; // IRQ Input Bus |
reg [31:0] current_irq; |
|
reg [12:0] state; // Current state |
reg [4:0] irq_cnt; // IRQ Frame counter |
|
reg found_stop; |
reg found_start; |
reg serirq_mode; |
|
wire irq_changed = (serirq_mode & (current_irq != irq_i)); |
|
always @(posedge clk_i or negedge nrst_i) |
if(~nrst_i) |
begin |
state <= `SERIRQ_ST_IDLE; |
serirq_oe <= 1'b0; |
serirq_o <= 4'b1; |
irq_cnt <= 5'h00; |
current_irq <= irq_i; |
end |
else begin |
case(state) |
`SERIRQ_ST_IDLE: |
begin |
serirq_oe <= 1'b0; |
irq_cnt <= 5'h00; |
serirq_o <= 1'b1; |
|
if(found_start == 1'b1) // Wait for Start cycle |
begin |
current_irq <= irq_i; |
if(irq_i[irq_cnt] == 1'b0) begin |
serirq_oe <= 1'b1; |
serirq_o <= 1'b0; |
end |
state <= `SERIRQ_ST_IRQ_R; |
end |
else if(irq_changed) begin |
current_irq <= irq_i; |
serirq_o <= 1'b0; |
serirq_oe <= 1'b1; |
state <= `SERIRQ_ST_IDLE; |
end else |
state <= `SERIRQ_ST_IDLE; |
end |
`SERIRQ_ST_IRQ: |
begin |
if(irq_i[irq_cnt] == 1'b0) begin |
serirq_oe <= 1'b1; |
serirq_o <= 1'b0; |
end |
if(found_stop == 1'b0) |
state <= `SERIRQ_ST_IRQ_R; |
else |
state <= `SERIRQ_ST_IDLE; |
end |
`SERIRQ_ST_IRQ_R: |
begin |
serirq_o <= 1'b1; |
if(found_stop == 1'b0) |
state <= `SERIRQ_ST_IRQ_T; |
else |
state <= `SERIRQ_ST_IDLE; |
end |
`SERIRQ_ST_IRQ_T: |
begin |
serirq_oe <= 1'b0; |
if(irq_cnt == 5'h1f) |
begin |
state <= `SERIRQ_ST_WAIT_STOP; |
end |
else begin |
irq_cnt <= irq_cnt + 1; |
if(found_stop == 1'b0) |
state <= `SERIRQ_ST_IRQ; |
else |
state <= `SERIRQ_ST_IDLE; |
end |
end |
`SERIRQ_ST_WAIT_STOP: |
begin |
if(found_stop == 1'b0) |
state <= `SERIRQ_ST_WAIT_STOP; |
else |
state <= `SERIRQ_ST_IDLE; |
end |
endcase |
end |
|
reg [3:0] stop_clk_cnt; |
|
// Look for STOP cycles |
always @(posedge clk_i or negedge nrst_i) |
if(~nrst_i) |
begin |
found_stop <= 1'b0; |
found_start <= 1'b0; |
serirq_mode <= `SERIRQ_MODE_CONTINUOUS; |
stop_clk_cnt <= 4'h0; |
end |
else begin |
if(serirq_i == 1'b0) begin |
stop_clk_cnt <= stop_clk_cnt + 1; |
end |
else begin |
case (stop_clk_cnt) |
4'h2: |
begin |
found_stop <= 1'b1; |
found_start <= 1'b0; |
serirq_mode <= `SERIRQ_MODE_QUIET; |
end |
4'h3: |
begin |
found_stop <= 1'b1; |
found_start <= 1'b0; |
serirq_mode <= `SERIRQ_MODE_CONTINUOUS; |
end |
4'h4: |
begin |
found_stop <= 1'b0; |
found_start <= 1'b1; |
end |
4'h6: |
begin |
found_stop <= 1'b0; |
found_start <= 1'b1; |
end |
4'h8: |
begin |
found_stop <= 1'b0; |
found_start <= 1'b1; |
end |
default: |
begin |
found_stop <= 1'b0; |
found_start <= 1'b0; |
end |
endcase |
stop_clk_cnt <= 4'h0; |
end |
end |
endmodule |
|
serirq_slave.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: serirq_defines.v
===================================================================
--- serirq_defines.v (nonexistent)
+++ serirq_defines.v (revision 20)
@@ -0,0 +1,53 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: serirq_defines.v,v 1.2 2008-12-27 19:46:18 hharte Exp $
+//// wb_lpc_defines.v ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+// Wishbone SERIRQ Host/Slave Interface Definitions
+`define SERIRQ_ST_IDLE 13'h000 // SERIRQ Idle state
+`define SERIRQ_ST_START 13'h001 // SERIRQ Start state
+`define SERIRQ_ST_START_R 13'h002 // SERIRQ Start state
+`define SERIRQ_ST_START_T 13'h004 // SERIRQ Start state
+`define SERIRQ_ST_IRQ 13'h008 // SERIRQ IRQ Frame State
+`define SERIRQ_ST_IRQ_R 13'h010 // SERIRQ IRQ Frame State
+`define SERIRQ_ST_IRQ_T 13'h020 // SERIRQ IRQ Frame State
+`define SERIRQ_ST_STOP 13'h040 // SERIRQ Stop State
+`define SERIRQ_ST_STOP_R 13'h080 // SERIRQ Stop State
+`define SERIRQ_ST_STOP_T 13'h100 // SERIRQ Stop State
+`define SERIRQ_ST_WAIT_STOP 13'h200
+
+`define SERIRQ_MODE_CONTINUOUS 1'b0 // Serirq "Continuous Mode"
+`define SERIRQ_MODE_QUIET 1'b1 // Serirq "Quiet Mode"
serirq_defines.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: serirq_host.v
===================================================================
--- serirq_host.v (nonexistent)
+++ serirq_host.v (revision 20)
@@ -0,0 +1,172 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: serirq_host.v,v 1.2 2008-12-27 19:46:18 hharte Exp $ ////
+//// serirq_host.v - SERIRQ Host Controller ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+`include "../../rtl/verilog/serirq_defines.v"
+
+module serirq_host(clk_i, nrst_i,
+ serirq_mode_i, irq_o,
+ serirq_o, serirq_i, serirq_oe
+);
+ // Wishbone Slave Interface
+ input clk_i;
+ input nrst_i; // Active low reset.
+ input serirq_mode_i; // Mode selection, 0=Continuous, 1=Quiet
+
+ // SERIRQ Master Interface
+ output reg serirq_o; // SERIRQ output
+ input serirq_i; // SERIRQ Input
+ output reg serirq_oe; // SERIRQ Output Enable
+
+ output reg [31:0] irq_o; // IRQ Output Bus
+
+ reg [12:0] state; // Current state
+ reg [4:0] irq_cnt; // IRQ Frame counter
+ reg [2:0] start_cnt; // START counter
+ reg [2:0] stop_cnt; // STOP counter
+ reg current_mode;
+
+ always @(posedge clk_i or negedge nrst_i)
+ if(~nrst_i)
+ begin
+ state <= `SERIRQ_ST_IDLE;
+ serirq_oe <= 1'b0;
+ serirq_o <= 4'b1;
+ irq_cnt <= 5'h00;
+ start_cnt <= 3'b000;
+ stop_cnt <= 2'b00;
+ irq_o <= 32'hFFFFFFFF;
+ current_mode <= `SERIRQ_MODE_CONTINUOUS;
+ end
+ else begin
+ case(state)
+ `SERIRQ_ST_IDLE:
+ begin
+ serirq_oe <= 1'b0;
+ start_cnt <= 3'b000;
+ stop_cnt <= 2'b00;
+ serirq_o <= 1'b1;
+ if((current_mode == `SERIRQ_MODE_QUIET) && (serirq_i == 1'b0)) begin
+ start_cnt <= 3'b010;
+ serirq_o <= 1'b0;
+ serirq_oe <= 1'b1;
+ state <= `SERIRQ_ST_START;
+ end
+ else if(current_mode == `SERIRQ_MODE_CONTINUOUS)
+ begin
+ start_cnt <= 3'b000;
+ state <= `SERIRQ_ST_START;
+ end
+ else if((current_mode == `SERIRQ_MODE_QUIET) && (serirq_mode_i == `SERIRQ_MODE_CONTINUOUS))
+ begin // Switch to Continuous mode by starting a new cycle to inform the slaves.
+ start_cnt <= 3'b000;
+ state <= `SERIRQ_ST_START;
+ end
+ else
+ state <= `SERIRQ_ST_IDLE;
+ end
+ `SERIRQ_ST_START:
+ begin
+ serirq_o <= 1'b0;
+ serirq_oe <= 1'b1;
+ irq_cnt <= 5'h00;
+ start_cnt <= start_cnt + 1;
+ if(start_cnt == 3'b111) begin
+ state <= `SERIRQ_ST_START_R;
+ end
+ else begin
+ state <= `SERIRQ_ST_START;
+ end
+ end
+ `SERIRQ_ST_START_R:
+ begin
+ serirq_o <= 1'b1;
+ state <= `SERIRQ_ST_START_T;
+ end
+ `SERIRQ_ST_START_T:
+ begin
+ serirq_oe <= 1'b0;
+ state <= `SERIRQ_ST_IRQ;
+ end
+ `SERIRQ_ST_IRQ:
+ begin
+ state <= `SERIRQ_ST_IRQ_R;
+ end
+ `SERIRQ_ST_IRQ_R:
+ begin
+ irq_o[irq_cnt] <= (serirq_i == 1'b0 ? 1'b0 : 1'b1);
+ state <= `SERIRQ_ST_IRQ_T;
+ end
+ `SERIRQ_ST_IRQ_T:
+ begin
+ if(irq_cnt == 5'h1f) begin
+ state <= `SERIRQ_ST_STOP;
+ end else begin
+ state <= `SERIRQ_ST_IRQ;
+ irq_cnt <= irq_cnt + 1;
+ end
+ end
+ `SERIRQ_ST_STOP:
+ begin
+ serirq_o <= 1'b0;
+ serirq_oe <= 1'b1;
+ stop_cnt <= stop_cnt + 1;
+ if(stop_cnt == (serirq_mode_i ? 2'b01 : 2'b10)) begin
+ state <= `SERIRQ_ST_STOP_R;
+ end
+ else begin
+ state <= `SERIRQ_ST_STOP;
+ end
+ end
+ `SERIRQ_ST_STOP_R:
+ begin
+ serirq_o <= 1'b1;
+ state <= `SERIRQ_ST_STOP_T;
+ end
+ `SERIRQ_ST_STOP_T:
+ begin
+ serirq_oe <= 1'b0;
+ state <= `SERIRQ_ST_IDLE;
+ current_mode <= serirq_mode_i;
+ end
+ endcase
+ end
+endmodule
+
+
serirq_host.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_lpc_periph.v
===================================================================
--- wb_lpc_periph.v (nonexistent)
+++ wb_lpc_periph.v (revision 20)
@@ -0,0 +1,423 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: wb_lpc_periph.v,v 1.4 2008-07-26 19:15:32 hharte Exp $ ////
+//// wb_lpc_periph.v - LPC Peripheral to Wishbone Master Bridge ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+`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
+//
+
+module wb_lpc_periph(clk_i, nrst_i, wbm_adr_o, wbm_dat_o, wbm_dat_i, wbm_sel_o, wbm_tga_o, wbm_we_o,
+ wbm_stb_o, wbm_cyc_o, wbm_ack_i, wbm_err_i,
+ dma_chan_o, dma_tc_o,
+ lframe_i, lad_i, lad_o, lad_oe
+);
+
+ // Wishbone Master Interface
+ input clk_i;
+ input nrst_i;
+ output reg [31:0] wbm_adr_o;
+ output reg [31:0] wbm_dat_o;
+ input [31:0] wbm_dat_i;
+ output reg [3:0] wbm_sel_o;
+ output reg [1:0] wbm_tga_o;
+ output reg wbm_we_o;
+ output reg wbm_stb_o;
+ output reg wbm_cyc_o;
+ input wbm_ack_i;
+ input wbm_err_i;
+
+ // LPC Slave Interface
+ input lframe_i; // LPC Frame input (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
+ output [2:0] dma_chan_o; // DMA Channel
+ output dma_tc_o; // DMA Terminal Count
+
+ reg [13:0] state; // Current state
+ reg [2:0] adr_cnt; // Address nibble counter
+ reg [3:0] dat_cnt; // Data nibble counter
+ 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 LPC input data.
+ reg mem_xfr; // LPC Memory Transfer (not I/O)
+ reg dma_xfr; // LPC DMA Transfer
+ reg fw_xfr; // LPC Firmware memory read/write
+ reg [2:0] xfr_len; // Number of nibbls for transfer
+ reg dma_tc; // DMA Terminal Count
+ reg [2:0] dma_chan; // DMA Channel
+
+ // These buffer enough state to delay the start of the next Wishbone cycle
+ // until the previous Firmware Write has completed.
+ reg [31:0] lpc_adr_reg; // Temporary storage for address received on LPC bus.
+ reg [31:0] lpc_dat_o; // Temporary storage for LPC output data.
+ reg lpc_write; // Holds current LPC transfer direction
+ reg [1:0] lpc_tga_o;
+ reg got_ack; // Set when ack has been received from wbm
+
+ assign dma_chan_o = dma_chan;
+ assign dma_tc_o = dma_tc;
+
+ always @(posedge clk_i or negedge nrst_i)
+ begin
+ if(~nrst_i)
+ begin
+ state <= `LPC_ST_IDLE;
+ lpc_adr_reg <= 32'h00000000;
+ lpc_dat_o <= 32'h00000000;
+ lpc_write <= 1'b0;
+ lpc_tga_o <= `WB_TGA_MEM;
+ lad_oe <= 1'b0;
+ lad_o <= 8'hFF;
+ lpc_dat_i <= 32'h00000000;
+ mem_xfr <= 1'b0;
+ dma_xfr <= 1'b0;
+ fw_xfr <= 1'b0;
+ xfr_len <= 3'b000;
+ dma_tc <= 1'b0;
+ dma_chan <= 3'b000;
+ end
+ else begin
+ case(state)
+ `LPC_ST_IDLE:
+ begin
+ dat_cnt <= 4'h0;
+ if(lframe_i) begin
+ lad_oe <= 1'b0;
+ xfr_len <= 3'b001;
+
+ if(lad_i == `LPC_START) begin
+ state <= `LPC_ST_CYCTYP;
+ lpc_write <= 1'b0;
+ fw_xfr <= 1'b0;
+ end
+ else if ((lad_i == `LPC_FW_WRITE) || (lad_i == `LPC_FW_READ)) begin
+ state <= `LPC_ST_ADDR;
+ lpc_write <= (lad_i == `LPC_FW_WRITE) ? 1'b1 : 1'b0;
+ adr_cnt <= 3'b000;
+ fw_xfr <= 1'b1;
+ dma_xfr <= 1'b0;
+ lpc_tga_o <= `WB_TGA_FW;
+ end
+ else
+ state <= `LPC_ST_IDLE;
+ end
+ else
+ state <= `LPC_ST_IDLE;
+ end
+ `LPC_ST_CYCTYP:
+ begin
+ lpc_write <= (lad_i[3] ? ~lad_i[1] : lad_i[1]); // Invert we_o if we are doing DMA.
+ adr_cnt <= (lad_i[2] ? 3'b000 : 3'b100);
+ if(lad_i[3]) begin // dma_xfr
+ lpc_tga_o <= `WB_TGA_DMA;
+ dma_xfr <= 1'b1;
+ mem_xfr <= 1'b0;
+ state <= `LPC_ST_CHAN;
+ end
+ else if(lad_i[2]) begin // mem_xfr
+ lpc_tga_o <= `WB_TGA_MEM;
+ dma_xfr <= 1'b0;
+ mem_xfr <= 1'b1;
+ state <= `LPC_ST_ADDR;
+ end
+ else begin
+ lpc_tga_o <= `WB_TGA_IO;
+ dma_xfr <= 1'b0;
+ mem_xfr <= 1'b0;
+ state <= `LPC_ST_ADDR;
+ end
+ end
+ `LPC_ST_ADDR:
+ begin
+ case(adr_cnt)
+ 3'h0: lpc_adr_reg[31:28] <= lad_i;
+ 3'h1: lpc_adr_reg[27:24] <= lad_i;
+ 3'h2: lpc_adr_reg[23:20] <= lad_i;
+ 3'h3: lpc_adr_reg[19:16] <= lad_i;
+ 3'h4: lpc_adr_reg[15:12] <= lad_i;
+ 3'h5: lpc_adr_reg[11: 8] <= lad_i;
+ 3'h6: lpc_adr_reg[ 7: 4] <= lad_i;
+ 3'h7: lpc_adr_reg[ 3: 0] <= lad_i;
+ endcase
+
+ adr_cnt <= adr_cnt + 1;
+
+ if(adr_cnt == 3'h7) // Last address nibble.
+ begin
+ if(~fw_xfr)
+ if(lpc_write)
+ state <= `LPC_ST_H_DATA;
+ else
+ state <= `LPC_ST_H_TAR1;
+ else // For firmware read/write, we need to read the MSIZE nibble
+ state <= `LPC_ST_SIZE;
+ end
+ else
+ state <= `LPC_ST_ADDR;
+ end
+ `LPC_ST_CHAN:
+ begin
+ lpc_adr_reg <= 32'h00000000; // Address lines not used for DMA.
+ dma_tc <= lad_i[3];
+ dma_chan <= lad_i[2:0];
+ 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
+ end
+endmodule
+
+
wb_lpc_periph.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_lpc_defines.v
===================================================================
--- wb_lpc_defines.v (nonexistent)
+++ wb_lpc_defines.v (revision 20)
@@ -0,0 +1,83 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// wb_lpc_defines.v ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+// 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_SYNC_READY 4'b0000 // LPC Sync Ready
+`define LPC_SYNC_SWAIT 4'b0101 // LPC Sync Short Wait (up to 8 cycles)
+`define LPC_SYNC_LWAIT 4'b0110 // LPC Sync Long Wait (no limit)
+`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 14'h000 // LPC Idle state
+`define LPC_ST_START 14'h001 // LPC Start state
+`define LPC_ST_CYCTYP 14'h002 // LPC Cycle Type State
+`define LPC_ST_ADDR 14'h004 // LPC Address state (4 cycles)
+`define LPC_ST_CHAN 14'h008 // LPC Address state (4 cycles)
+`define LPC_ST_SIZE 14'h010 // LPC Address state (4 cycles)
+`define LPC_ST_H_DATA 14'h020 // LPC Host Data state (2 cycles)
+`define LPC_ST_P_DATA 14'h040 // LPC Peripheral Data state (2 cycles)
+`define LPC_ST_H_TAR1 14'h080 // LPC Host Turnaround 1 (Drive LAD 4'hF)
+`define LPC_ST_H_TAR2 14'h100 // LPC Host Turnaround 2 (Float LAD)
+`define LPC_ST_P_TAR1 14'h200 // LPC Peripheral Turnaround 1 (Drive LAD = 4'hF)
+`define LPC_ST_P_TAR2 14'h400 // LPC Peripheral Turnaround 2 (Float LAD)
+`define LPC_ST_WB_RETIRE 14'h400 // Retire Wishbone transfer (Host only), ends WB cycle.
+`define LPC_ST_SYNC 14'h800 // LPC Sync State (may be multiple cycles for wait-states)
+`define LPC_ST_P_WAIT1 14'h1000 // LPC Sync State (may be multiple cycles for wait-states)
+`define LPC_ST_FWW_SYNC 14'h2000 // LPC Sync State for Firmware Writes (must not generate 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_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
wb_lpc_defines.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_lpc_host.v
===================================================================
--- wb_lpc_host.v (nonexistent)
+++ wb_lpc_host.v (revision 20)
@@ -0,0 +1,383 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $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 ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+`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
+//
+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,
+ 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;
+ output reg wbs_err_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
+
+ reg [13: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
+
+ // 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;
+ wbs_err_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;
+ wbs_err_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(~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 firmware 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
+ 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
+ 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) || (lad_i == `LPC_SYNC_MORE)) begin
+ if(wbs_wr) begin
+ state <= `LPC_ST_P_TAR1;
+ end
+ else begin
+ state <= `LPC_ST_P_DATA;
+ end
+ end else if(lad_i == `LPC_SYNC_ERROR) begin
+ dat_cnt <= { xfr_len, 1'b1 }; // Terminate data transfer
+ wbs_err_o <= 1'b1; // signal wishbone error
+ state <= `LPC_ST_P_TAR1;
+ end else begin
+ state <= `LPC_ST_SYNC;
+ end
+ 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 begin
+ if(fw_xfr) // Firmware transfer does not have TAR between bytes.
+ state <= `LPC_ST_P_DATA;
+ else
+ state <= `LPC_ST_SYNC;
+ end
+ 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;
+ wbs_err_o <= 1'b0;
+ if(wbs_acc) begin
+ state <= `LPC_ST_WB_RETIRE;
+ end
+ else begin
+ state <= `LPC_ST_IDLE;
+ end
+ end
+ endcase
+ end
+
+endmodule
+
+
wb_lpc_host.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_regfile.v
===================================================================
--- wb_regfile.v (nonexistent)
+++ wb_regfile.v (revision 20)
@@ -0,0 +1,182 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: wb_regfile.v,v 1.3 2008-07-26 19:15:32 hharte Exp $ ////
+//// wb_regfile.v - Small Wishbone register file for testing ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module wb_regfile (clk_i, nrst_i, wb_adr_i, wb_dat_o, wb_dat_i, wb_sel_i, wb_we_i,
+ wb_stb_i, wb_cyc_i, wb_ack_o, wb_err_o, ws_i, datareg0, datareg1);
+
+ input clk_i;
+ input nrst_i;
+ input [3:0] wb_adr_i;
+ output reg [31:0] wb_dat_o;
+ input [31:0] wb_dat_i;
+ input [3:0] wb_sel_i;
+ input wb_we_i;
+ input wb_stb_i;
+ input wb_cyc_i;
+ output reg wb_ack_o;
+ output wb_err_o;
+ input [7:0] ws_i;
+ output [31:0] datareg0;
+ output [31:0] datareg1;
+ reg [7:0] waitstate;
+
+ //
+ // generate wishbone register bank writes
+ wire wb_acc = wb_cyc_i & wb_stb_i; // WISHBONE access
+ wire wb_wr = wb_acc & wb_we_i; // WISHBONE write access
+
+ reg [7:0] datareg0_0;
+ reg [7:0] datareg0_1;
+ reg [7:0] datareg0_2;
+ reg [7:0] datareg0_3;
+
+ reg [7:0] datareg1_0;
+ reg [7:0] datareg1_1;
+ reg [7:0] datareg1_2;
+ reg [7:0] datareg1_3;
+
+ always @(posedge clk_i or negedge nrst_i)
+ if (~nrst_i) // reset registers
+ begin
+ datareg0_0 <= 8'h00;
+ datareg0_1 <= 8'h01;
+ datareg0_2 <= 8'h02;
+ datareg0_3 <= 8'h03;
+ datareg1_0 <= 8'h10;
+ datareg1_1 <= 8'h11;
+ datareg1_2 <= 8'h12;
+ datareg1_3 <= 8'h13;
+ wb_ack_o <= 1'b0;
+ waitstate <= 4'b0;
+ wb_dat_o <= 32'h00000000;
+ end
+ else if(wb_wr) // wishbone write cycle
+ case (wb_sel_i)
+ 4'b0000:
+ case (wb_adr_i) // synopsys full_case parallel_case
+ 4'b0000: datareg0_0 <= wb_dat_i[7:0];
+ 4'b0001: datareg0_1 <= wb_dat_i[7:0];
+ 4'b0010: datareg0_2 <= wb_dat_i[7:0];
+ 4'b0011: datareg0_3 <= wb_dat_i[7:0];
+ 4'b0100: datareg1_0 <= wb_dat_i[7:0];
+ 4'b0101: datareg1_1 <= wb_dat_i[7:0];
+ 4'b0110: datareg1_2 <= wb_dat_i[7:0];
+ 4'b0111: datareg1_3 <= wb_dat_i[7:0];
+ endcase
+ 4'b0001:
+ case (wb_adr_i) // synopsys full_case parallel_case
+ 4'b0000: datareg0_0 <= wb_dat_i[7:0];
+ 4'b0001: datareg0_1 <= wb_dat_i[7:0];
+ 4'b0010: datareg0_2 <= wb_dat_i[7:0];
+ 4'b0011: datareg0_3 <= wb_dat_i[7:0];
+ 4'b0100: datareg1_0 <= wb_dat_i[7:0];
+ 4'b0101: datareg1_1 <= wb_dat_i[7:0];
+ 4'b0110: datareg1_2 <= wb_dat_i[7:0];
+ 4'b0111: datareg1_3 <= wb_dat_i[7:0];
+ endcase
+ 4'b0011:
+ {datareg0_1, datareg0_0} <= wb_dat_i[15:0];
+// case (wb_adr_i) // synopsys full_case parallel_case
+// 3'b000: {datareg0_1, datareg0_0} <= wb_dat_i[15:0];
+// endcase
+ 4'b1111:
+ {datareg0_3, datareg0_2, datareg0_1, datareg0_0} <= wb_dat_i[31:0];
+// case (wb_adr_i) // synopsys full_case parallel_case
+// 3'b000: {datareg0_3, datareg0_2, datareg0_1, datareg0_0} <= wb_dat_i[31:0];
+// endcase
+
+ endcase
+ // generate dat_o
+ always @(posedge clk_i)
+ case (wb_sel_i)
+ 4'b0000:
+ case (wb_adr_i) // synopsys full_case parallel_case
+ 4'b0000: wb_dat_o[7:0] <= datareg0_0;
+ 4'b0001: wb_dat_o[7:0] <= datareg0_1;
+ 4'b0010: wb_dat_o[7:0] <= datareg0_2;
+ 4'b0011: wb_dat_o[7:0] <= datareg0_3;
+ 4'b0100: wb_dat_o[7:0] <= datareg1_0;
+ 4'b0101: wb_dat_o[7:0] <= datareg1_1;
+ 4'b0110: wb_dat_o[7:0] <= datareg1_2;
+ 4'b0111: wb_dat_o[7:0] <= datareg1_3;
+ endcase
+ 4'b0001:
+ case (wb_adr_i) // synopsys full_case parallel_case
+ 4'b0000: wb_dat_o[7:0] <= datareg0_0;
+ 4'b0001: wb_dat_o[7:0] <= datareg0_1;
+ 4'b0010: wb_dat_o[7:0] <= datareg0_2;
+ 4'b0011: wb_dat_o[7:0] <= datareg0_3;
+ 4'b0100: wb_dat_o[7:0] <= datareg1_0;
+ 4'b0101: wb_dat_o[7:0] <= datareg1_1;
+ 4'b0110: wb_dat_o[7:0] <= datareg1_2;
+ 4'b0111: wb_dat_o[7:0] <= datareg1_3;
+ endcase
+ 4'b0011:
+ wb_dat_o[15:0] <= {datareg0_1, datareg0_0};
+ 4'b1111:
+ wb_dat_o[31:0] <= {datareg0_3, datareg0_2, datareg0_1, datareg0_0};
+ endcase
+
+ // generate ack_o
+ always @(posedge clk_i or negedge nrst_i)
+ if (nrst_i) begin // not in reset
+ if (ws_i == 0) begin
+ wb_ack_o <= wb_acc & !wb_ack_o;
+ end else
+ if((waitstate == 4'b0) && (ws_i != 0)) begin
+ wb_ack_o <= 1'b0;
+ if(wb_acc) begin
+ waitstate <= waitstate + 1;
+ end
+ end
+ else begin
+ if(wb_acc) waitstate <= waitstate + 1;
+ if(waitstate == ws_i) begin
+ if(wb_acc) wb_ack_o <= 1'b1;
+ waitstate <= 1'b0;
+ end
+ end
+ end
+
+ assign datareg0 = { datareg0_3, datareg0_2, datareg0_1, datareg0_0 };
+ assign datareg1 = { datareg1_3, datareg1_2, datareg1_1, datareg1_0 };
+
+ // Generate an error for registers 0x8-0xF
+ assign wb_err_o = wb_ack_o & wb_adr_i[3];
+
+endmodule
wb_regfile.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_dreq_host.v
===================================================================
--- wb_dreq_host.v (nonexistent)
+++ wb_dreq_host.v (revision 20)
@@ -0,0 +1,103 @@
+//
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: wb_dreq_host.v,v 1.2 2008-03-05 05:50:59 hharte Exp $ ////
+//// wb_dreq_host.v - Wishbone DMA Controller for LPC Host ////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+`include "../../rtl/verilog/wb_lpc_defines.v"
+
+module wb_dreq_host(clk_i, nrst_i,
+ dma_chan_o, dma_req_o,
+ ldrq_i
+);
+ // Wishbone Slave Interface
+ input clk_i;
+ input nrst_i; // Active low reset.
+
+ // Private DMA Interface
+ output reg [2:0] dma_chan_o;
+ output reg dma_req_o;
+
+ // LPC Bus DMA Request Input
+ input ldrq_i;
+
+ reg [1:0] adr_cnt;
+ reg [3:0] state;
+
+ always @(posedge clk_i or negedge nrst_i)
+ if(~nrst_i)
+ begin
+ state <= `LDRQ_ST_IDLE;
+ dma_chan_o <= 3'h0;
+ dma_req_o <= 3'h0;
+ adr_cnt <= 2'b00;
+ end
+ else begin
+ case(state)
+ `LDRQ_ST_IDLE:
+ begin
+ dma_req_o <= 1'b0;
+ if(~ldrq_i) begin
+ state <= `LDRQ_ST_ADDR;
+ adr_cnt <= 2'h2;
+ end
+ end
+ `LDRQ_ST_ADDR:
+ begin
+ dma_chan_o[adr_cnt] <= ldrq_i;
+ adr_cnt <= adr_cnt - 1;
+
+ if(adr_cnt == 2'h0)
+ state <= `LDRQ_ST_ACT;
+ end
+ `LDRQ_ST_ACT:
+ begin
+ dma_req_o <= ldrq_i;
+ state <= `LDRQ_ST_DONE;
+ end
+ `LDRQ_ST_DONE:
+ begin
+ dma_req_o <= 1'b0;
+ state <= `LDRQ_ST_IDLE;
+ end
+ endcase
+ end
+
+endmodule
+
+
wb_dreq_host.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: wb_dreq_periph.v
===================================================================
--- wb_dreq_periph.v (nonexistent)
+++ wb_dreq_periph.v (revision 20)
@@ -0,0 +1,100 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// $Id: wb_dreq_periph.v,v 1.2 2008-03-05 05:50:59 hharte Exp $////
+//// wb_dreq_periph.v - Wishbone DMA Requestor for LPC Peripheral////
+//// ////
+//// This file is part of the Wishbone LPC Bridge project ////
+//// http://www.opencores.org/projects/wb_lpc/ ////
+//// ////
+//// Author: ////
+//// - Howard M. Harte (hharte@opencores.org) ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2008 Howard M. Harte ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+`include "../../rtl/verilog/wb_lpc_defines.v"
+
+module wb_dreq_periph(clk_i, nrst_i,
+ dma_chan_i, dma_req_i,
+ ldrq_o
+);
+ // Wishbone Slave Interface
+ input clk_i;
+ input nrst_i; // Active low reset.
+
+ // Private DMA Interface
+ input [2:0] dma_chan_i;
+ input dma_req_i;
+
+ // LPC Bus DMA Request Output
+ output reg ldrq_o;
+
+ reg [1:0] adr_cnt;
+ reg [3:0] state;
+
+ always @(posedge clk_i or negedge nrst_i)
+ if(~nrst_i)
+ begin
+ state <= `LDRQ_ST_IDLE;
+ ldrq_o <= 1'b1; // LDRQ# Idle
+ adr_cnt <= 2'b00;
+ end
+ else begin
+ case(state)
+ `LDRQ_ST_IDLE:
+ begin
+ if(dma_req_i) begin
+ ldrq_o <= 1'b0;
+ state <= `LDRQ_ST_ADDR;
+ adr_cnt <= 2'h2;
+ end
+ end
+ `LDRQ_ST_ADDR:
+ begin
+ ldrq_o <= dma_chan_i[adr_cnt];
+ adr_cnt <= adr_cnt - 1;
+
+ if(adr_cnt == 2'h0)
+ state <= `LDRQ_ST_ACT;
+ end
+ `LDRQ_ST_ACT:
+ begin
+ ldrq_o <= 1'b1;
+ state <= `LDRQ_ST_DONE;
+ end
+ `LDRQ_ST_DONE:
+ begin
+ ldrq_o <= 1'b1;
+ state <= `LDRQ_ST_IDLE;
+ end
+ endcase
+ end
+
+endmodule
+
wb_dreq_periph.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 20)
.
Property changes :
Added: svn:ignore
## -0,0 +1 ##
+.svn