LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Cvs-checkins > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: cvs at opencores.org<cvs@o...>
    Date: Sat Jul 26 21:15:32 CEST 2008
    Subject: [cvs-checkins] MODIFIED: wb_lpc ...
    Top
    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

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.