|
Message
From: cvs at opencores.org<cvs@o...>
Date: Sat Jul 26 21:15:32 CEST 2008
Subject: [cvs-checkins] MODIFIED: wb_lpc ...
Date: 00/08/07 26:21:15 Modified: wb_lpc/rtl/verilog wb_lpc_defines.v wb_lpc_host.v wb_lpc_periph.v wb_regfile.v Log: Fix bugs: 25-Jul-2008 LPC firmware writes must not insert wait-states. 22-Jul-2008 LPC DMA does not report READY+MORE for multi-byte transfers Add feature: 23-Jul-2008 propagate Wishbone errors across LPC interface Improve Testbench: Ability to test multiple wait-states on LPC Peripheral Wishbone Master interface. Check wbs_err_o from LPC Host. Rebuild examples with the fixes above. Revision Changes Path 1.4 wb_lpc/rtl/verilog/wb_lpc_defines.v http://www.opencores.org/cvsweb.shtml/wb_lpc/rtl/verilog/wb_lpc_defines.v.diff?r1=1.3&r2=1.4 (In the diff below, changes in quantity of whitespace are not shown.) Index: wb_lpc_defines.v =================================================================== RCS file: /cvsroot/hharte/wb_lpc/rtl/verilog/wb_lpc_defines.v,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -r1.3 -r1.4 --- wb_lpc_defines.v 10 Mar 2008 14:08:13 -0000 1.3 +++ wb_lpc_defines.v 26 Jul 2008 19:15:31 -0000 1.4 @@ -48,21 +48,22 @@ `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_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 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 1.4 wb_lpc/rtl/verilog/wb_lpc_host.v http://www.opencores.org/cvsweb.shtml/wb_lpc/rtl/verilog/wb_lpc_host.v.diff?r1=1.3&r2=1.4 (In the diff below, changes in quantity of whitespace are not shown.) Index: wb_lpc_host.v =================================================================== RCS file: /cvsroot/hharte/wb_lpc/rtl/verilog/wb_lpc_host.v,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -r1.3 -r1.4 --- wb_lpc_host.v 22 Jul 2008 13:46:42 -0000 1.3 +++ wb_lpc_host.v 26 Jul 2008 19:15:31 -0000 1.4 @@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////
//// ////
-//// $Id: wb_lpc_host.v,v 1.3 2008/07/22 13:46:42 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 ////
//// ////
//// This file is part of the Wishbone LPC Bridge project ////
@@ -52,7 +52,7 @@
// 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_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
);
@@ -68,6 +68,7 @@
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)
@@ -79,7 +80,7 @@
input [2:0] dma_chan_i; // DMA Channel
input dma_tc_i; // DMA Terminal Count
- reg [12:0] state; // Current state
+ 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
@@ -105,6 +106,7 @@
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;
@@ -117,6 +119,7 @@
`LPC_ST_IDLE:
begin
wbs_ack_o <= 1'b0;
+ wbs_err_o <= 1'b0;
lframe_o <= 1'b0;
dat_cnt <= 4'h0;
@@ -294,16 +297,21 @@
`LPC_ST_SYNC:
begin
lad_oe <= 1'b0; // float LAD
- if(lad_i == `LPC_SYNC_READY) begin
+ if((lad_i == `LPC_SYNC_READY) || (lad_i == `LPC_SYNC_MORE)) begin
if(wbs_wr) begin
state <= `LPC_ST_P_TAR1;
end
- else
+ else begin
state <= `LPC_ST_P_DATA;
end
- else
+ 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
@@ -359,6 +367,7 @@
`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
1.4 wb_lpc/rtl/verilog/wb_lpc_periph.v
http://www.opencores.org/cvsweb.shtml/wb_lpc/rtl/verilog/wb_lpc_periph.v.diff?r1=1.3&r2=1.4
(In the diff below, changes in quantity of whitespace are not shown.)
Index: wb_lpc_periph.v
===================================================================
RCS file: /cvsroot/hharte/wb_lpc/rtl/verilog/wb_lpc_periph.v,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- wb_lpc_periph.v 22 Jul 2008 13:46:42 -0000 1.3
+++ wb_lpc_periph.v 26 Jul 2008 19:15:32 -0000 1.4
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////
//// ////
-//// $Id: wb_lpc_periph.v,v 1.3 2008/07/22 13:46:42 hharte Exp $ ////
+//// $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 ////
@@ -53,7 +53,7 @@
//
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_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
);
@@ -70,6 +70,7 @@
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)
@@ -81,14 +82,13 @@
output [2:0] dma_chan_o; // DMA Channel
output dma_tc_o; // DMA Terminal Count
- reg [12:0] state; // Current state
+ 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 input data.
- reg [3:0] start_type; // Type of LPC start cycle
+ 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
@@ -96,25 +96,29 @@
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;
- wbm_adr_o <= 16'h0000;
- wbm_dat_o <= 32'h00000000;
- wbm_sel_o <= 4'b0000;
- wbm_tga_o <= `WB_TGA_MEM;
- wbm_we_o <= 1'b0;
- wbm_stb_o <= 1'b0;
- wbm_cyc_o <= 1'b0;
+ 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'h00;
- start_type <= 4'b0000;
- wbm_tga_o <= `WB_TGA_MEM;
+ lpc_dat_i <= 32'h00000000;
mem_xfr <= 1'b0;
dma_xfr <= 1'b0;
fw_xfr <= 1'b0;
@@ -127,33 +131,22 @@
`LPC_ST_IDLE:
begin
dat_cnt <= 4'h0;
- if(lframe_i)
- begin
- start_type <= lad_i;
- wbm_sel_o <= 4'b0000;
- wbm_stb_o <= 1'b0;
- wbm_cyc_o <= 1'b0;
+ if(lframe_i) begin
lad_oe <= 1'b0;
xfr_len <= 3'b001;
if(lad_i == `LPC_START) begin
state <= `LPC_ST_CYCTYP;
- wbm_we_o <= 1'b0;
+ lpc_write <= 1'b0;
fw_xfr <= 1'b0;
end
- else if (lad_i == `LPC_FW_READ) begin
- state <= `LPC_ST_ADDR;
- wbm_we_o <= 1'b0;
- adr_cnt <= 3'b000;
- fw_xfr <= 1'b1;
- wbm_tga_o <= `WB_TGA_FW;
- end
- else if (lad_i == `LPC_FW_WRITE) begin
+ else if ((lad_i == `LPC_FW_WRITE) || (lad_i == `LPC_FW_READ)) begin
state <= `LPC_ST_ADDR;
- wbm_we_o <= 1'b1;
+ lpc_write <= (lad_i == `LPC_FW_WRITE) ? 1'b1 : 1'b0;
adr_cnt <= 3'b000;
fw_xfr <= 1'b1;
- wbm_tga_o <= `WB_TGA_FW;
+ dma_xfr <= 1'b0;
+ lpc_tga_o <= `WB_TGA_FW;
end
else
state <= `LPC_ST_IDLE;
@@ -163,45 +156,38 @@
end
`LPC_ST_CYCTYP:
begin
- wbm_we_o <= (lad_i[3] ? ~lad_i[1] : lad_i[1]); // Invert we_o if we are doing DMA.
- mem_xfr <= lad_i[2];
- dma_xfr <= lad_i[3];
+ 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]) // dma_xfr)
- wbm_tga_o <= `WB_TGA_DMA;
- else if(lad_i[2]) //mem_xfr)
- wbm_tga_o <= `WB_TGA_MEM;
- else
- wbm_tga_o <= `WB_TGA_IO;
-
- if(lad_i[3]) //dma_xfr)
- begin
+ 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
- begin
+ 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:
- wbm_adr_o[31:28] <= lad_i;
- 3'h1:
- wbm_adr_o[27:24] <= lad_i;
- 3'h2:
- wbm_adr_o[23:20] <= lad_i;
- 3'h3:
- wbm_adr_o[19:16] <= lad_i;
- 3'h4:
- wbm_adr_o[15:12] <= lad_i;
- 3'h5:
- wbm_adr_o[11:8] <= lad_i;
- 3'h6:
- wbm_adr_o[7:4] <= lad_i;
- 3'h7:
- wbm_adr_o[3:0] <= lad_i;
+ 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;
@@ -209,7 +195,7 @@
if(adr_cnt == 3'h7) // Last address nibble.
begin
if(~fw_xfr)
- if(wbm_we_o)
+ if(lpc_write)
state <= `LPC_ST_H_DATA;
else
state <= `LPC_ST_H_TAR1;
@@ -221,7 +207,7 @@
end
`LPC_ST_CHAN:
begin
- wbm_adr_o <= 32'h00000000; // Address lines not used for DMA.
+ 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;
@@ -229,33 +215,13 @@
`LPC_ST_SIZE:
begin
case(lad_i)
- 4'h0:
- begin
- xfr_len <= 3'b001;
- wbm_sel_o <= `WB_SEL_BYTE;
- end
- 4'h1:
- begin
- xfr_len <= 3'b010;
- wbm_sel_o <= `WB_SEL_SHORT;
- end
- 4'h2: // Firmware transfer uses '2' for 4-byte transfer.
- begin
- xfr_len <= 3'b100;
- wbm_sel_o <= `WB_SEL_WORD;
- end
- 4'h3: // DMA uses '3' for 4-byte transfer.
- begin
- xfr_len <= 3'b100;
- wbm_sel_o <= `WB_SEL_WORD;
- end
- default:
- begin
- xfr_len <= 3'b001;
- wbm_sel_o <= 4'b0000;
- end
+ 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(wbm_we_o)
+ if(lpc_write)
state <= `LPC_ST_H_DATA;
else
state <= `LPC_ST_H_TAR1;
@@ -263,22 +229,14 @@
`LPC_ST_H_DATA:
begin
case(dat_cnt)
- 4'h0:
- wbm_dat_o[3:0] <= lad_i;
- 4'h1:
- wbm_dat_o[7:4] <= lad_i;
- 4'h2:
- wbm_dat_o[11:8] <= lad_i;
- 4'h3:
- wbm_dat_o[15:12] <= lad_i;
- 4'h4:
- wbm_dat_o[19:16] <= lad_i;
- 4'h5:
- wbm_dat_o[23:20] <= lad_i;
- 4'h6:
- wbm_dat_o[27:24] <= lad_i;
- 4'h7:
- wbm_dat_o[31:28] <= lad_i;
+ 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;
@@ -297,70 +255,70 @@
`LPC_ST_H_TAR1:
begin
- if(((byte_cnt == xfr_len) & wbm_we_o) | ((byte_cnt == 0) & ~wbm_we_o))
- begin
- wbm_stb_o <= 1'b1;
- wbm_cyc_o <= 1'b1;
- end
+ // It is ok to start the Wishbone Cycle, done below...
state <= `LPC_ST_H_TAR2;
end
`LPC_ST_H_TAR2:
begin
- state <= `LPC_ST_SYNC;
+ 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
- lad_o <= `LPC_SYNC_SWAIT;
end
`LPC_ST_SYNC:
begin
lad_oe <= 1'b1; // start driving LAD
- if(((byte_cnt == xfr_len) & wbm_we_o) | ((byte_cnt == 0) & ~wbm_we_o)) begin
- if(wbm_ack_i)
- begin
+ // 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
- wbm_stb_o <= 1'b0; // End Wishbone cycle.
- wbm_cyc_o <= 1'b0;
- if(wbm_we_o)
state <= `LPC_ST_P_TAR1;
- else
- begin
- lpc_dat_i <= wbm_dat_i[31:0];
+ 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
+ else begin
state <= `LPC_ST_SYNC;
lad_o <= `LPC_SYNC_SWAIT;
end
end
else begin // Multi-byte transfer, just ack right away.
- lad_o <= `LPC_SYNC_READY; // Ready
- if(wbm_we_o)
+ if(lpc_write) begin
+ lad_o <= (dma_xfr) ? `LPC_SYNC_MORE : `LPC_SYNC_READY;
state <= `LPC_ST_P_TAR1;
- else
+ 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];
+ 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;
@@ -392,7 +350,7 @@
state <= `LPC_ST_IDLE;
end
else begin
- if(wbm_we_o) begin // DMA READ (Host to Peripheral)
+ if(lpc_write) begin // DMA READ (Host to Peripheral)
state <= `LPC_ST_P_WAIT1;
end
else begin // unhandled READ case
@@ -406,6 +364,60 @@
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
1.3 wb_lpc/rtl/verilog/wb_regfile.v
http://www.opencores.org/cvsweb.shtml/wb_lpc/rtl/verilog/wb_regfile.v.diff?r1=1.2&r2=1.3
(In the diff below, changes in quantity of whitespace are not shown.)
Index: wb_regfile.v
===================================================================
RCS file: /cvsroot/hharte/wb_lpc/rtl/verilog/wb_regfile.v,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- wb_regfile.v 5 Mar 2008 05:50:59 -0000 1.2
+++ wb_regfile.v 26 Jul 2008 19:15:32 -0000 1.3
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////
//// ////
-//// $Id: wb_regfile.v,v 1.2 2008/03/05 05:50:59 hharte Exp $ ////
+//// $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 ////
@@ -37,11 +37,11 @@
//////////////////////////////////////////////////////////////////////
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, datareg0, datareg1);
+ wb_stb_i, wb_cyc_i, wb_ack_o, wb_err_o, ws_i, datareg0, datareg1);
input clk_i;
input nrst_i;
- input [2:0] wb_adr_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;
@@ -49,8 +49,11 @@
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
@@ -78,30 +81,33 @@
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
- 3'b000: datareg0_0 <= wb_dat_i[7:0];
- 3'b001: datareg0_1 <= wb_dat_i[7:0];
- 3'b010: datareg0_2 <= wb_dat_i[7:0];
- 3'b011: datareg0_3 <= wb_dat_i[7:0];
- 3'b100: datareg1_0 <= wb_dat_i[7:0];
- 3'b101: datareg1_1 <= wb_dat_i[7:0];
- 3'b110: datareg1_2 <= wb_dat_i[7:0];
- 3'b111: datareg1_3 <= wb_dat_i[7:0];
+ 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
- 3'b000: datareg0_0 <= wb_dat_i[7:0];
- 3'b001: datareg0_1 <= wb_dat_i[7:0];
- 3'b010: datareg0_2 <= wb_dat_i[7:0];
- 3'b011: datareg0_3 <= wb_dat_i[7:0];
- 3'b100: datareg1_0 <= wb_dat_i[7:0];
- 3'b101: datareg1_1 <= wb_dat_i[7:0];
- 3'b110: datareg1_2 <= wb_dat_i[7:0];
- 3'b111: datareg1_3 <= wb_dat_i[7:0];
+ 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];
@@ -120,25 +126,25 @@
case (wb_sel_i)
4'b0000:
case (wb_adr_i) // synopsys full_case parallel_case
- 3'b000: wb_dat_o[7:0] <= datareg0_0;
- 3'b001: wb_dat_o[7:0] <= datareg0_1;
- 3'b010: wb_dat_o[7:0] <= datareg0_2;
- 3'b011: wb_dat_o[7:0] <= datareg0_3;
- 3'b100: wb_dat_o[7:0] <= datareg1_0;
- 3'b101: wb_dat_o[7:0] <= datareg1_1;
- 3'b110: wb_dat_o[7:0] <= datareg1_2;
- 3'b111: wb_dat_o[7:0] <= datareg1_3;
+ 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
- 3'b000: wb_dat_o[7:0] <= datareg0_0;
- 3'b001: wb_dat_o[7:0] <= datareg0_1;
- 3'b010: wb_dat_o[7:0] <= datareg0_2;
- 3'b011: wb_dat_o[7:0] <= datareg0_3;
- 3'b100: wb_dat_o[7:0] <= datareg1_0;
- 3'b101: wb_dat_o[7:0] <= datareg1_1;
- 3'b110: wb_dat_o[7:0] <= datareg1_2;
- 3'b111: wb_dat_o[7:0] <= datareg1_3;
+ 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};
@@ -147,10 +153,30 @@
endcase
// generate ack_o
- always @(posedge clk_i)
- wb_ack_o <= #1 wb_acc & !wb_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
|
 |