📄 pci_memory.v
字号:
while ((TRDY_reg && STOP) || FRAME == 0) @(posedge CLK) if ((IRDY == 0) && (TRDY == 0)) begin PAR_reg <= parity_bit; PAR_en <= 1; // Read the next value read_tmp = $pci_memory_peek(memory_fd, address, bar_flag); AD_reg <= read_tmp; parity_bit <= ^{read_tmp, C_BE}; // Linear addressing. address <= address + 4; // Randomly introduce target disconnects. if (STOP_en && STOP_reg == 0) begin TRDY_reg <= 1; if (FRAME == 0 && TRDY_reg == 1) begin $display("PCI MEMORY: master not honoring read disconnect!"); $display("PCI MEMORY: Forcing the issue via TRDY#=1."); $display("PCI MEMORY: Stopping. Resume if you dare."); $stop; end end else if (discon_rate && ($random%discon_rate == 0)) begin STOP_reg <= 0; end end // Transaction done. Turn off drivers. TRDY_reg <= 1; DEVSEL_reg <= 1; STOP_reg <= 0; AD_en <= 0; TRDY_en <= 0; DEVSEL_en <= 0; STOP_en <= 0; PAR_reg <= parity_bit; PAR_en <= 1; @(posedge CLK) PAR_en <= 0; end endtask // do_memory_read task do_memory_write; input bar_flag; begin address = AD & ~BAR0_MASK; // Fast timing, respond immediately DEVSEL_reg <= 0; DEVSEL_en <= 1; @(posedge CLK) ; // advance to turnaround cycle TRDY_reg <= 0; STOP_reg <= 1; TRDY_en <= 1; STOP_en <= 1; write_mask = { {8{C_BE[3]}}, {8{C_BE[2]}}, {8{C_BE[1]}}, {8{C_BE[0]}}}; write_val = $pci_memory_peek(memory_fd, address, bar_flag); write_val = (write_val&write_mask) | (AD&~write_mask); if ((IRDY == 0) && (TRDY == 0)) begin // Store the next value $pci_memory_poke(memory_fd, address, write_val, bar_flag); // Linear addressing. address <= address + 4; end // Keep reading so long as the master does not // stop the transaction. while (FRAME == 0) @(posedge CLK) if ((IRDY == 0) && (TRDY == 0)) begin write_mask = { {8{C_BE[3]}}, {8{C_BE[2]}}, {8{C_BE[1]}}, {8{C_BE[0]}}}; write_val = $pci_memory_peek(memory_fd, address, bar_flag); write_val = (write_val&write_mask) | (AD&~write_mask); // Store the next value $pci_memory_poke(memory_fd, address, write_val, bar_flag); // Linear addressing. address <= address + 4; // Randomly introduce target disconnects. if (STOP_en && STOP_reg == 0) begin TRDY_reg <= 1; if (FRAME == 0 && TRDY_reg == 1) begin $display("PCI MEMORY: master not honoring write disconnect!"); $display("PCI MEMORY: Forcing the issue via TRDY#=1."); $display("PCI MEMORY: Stopping. Resume if you dare."); $stop; end end else if (discon_rate && ($random%discon_rate == 0)) begin STOP_reg <= 0; end end // Transaction done. Turn off drivers. TRDY_reg <= 1; DEVSEL_reg <= 1; TRDY_en <= 0; DEVSEL_en <= 0; STOP_reg <= 1; STOP_en <= 0; end endtask // do_memory_write task do_bar2_read; begin case (AD[11:2]) 9'b000000000: AD_reg = {30'h0, dma_fifo, dma_go}; 9'b000000001: AD_reg = dma_external; 9'b000000010: AD_reg = dma_memory; 9'b000000011: AD_reg = dma_count; default: AD_reg = 32'hx; endcase // case(AD[11:2]) TRDY_reg <= 0; DEVSEL_reg <= 0; @(posedge CLK) ; AD_en <= 1; TRDY_en <= 1; DEVSEL_en <= 1; @(posedge CLK) ; // Parity bit is delayed one clock. PAR_en <= 1; PAR_reg <= ^{AD_reg, C_BE}; while (IRDY == 1) @(posedge CLK) ; TRDY_reg <= 1; TRDY_en <= 0; DEVSEL_reg <= 1; DEVSEL_en <= 0; @(posedge CLK) ; AD_en <= 0; PAR_en <= 0; end endtask // do_bar2_read task do_bar2_write; begin // Save the address from the address phase. address = AD; TRDY_reg <= 0; DEVSEL_reg <= 0; // Even fast timing response requires that we wait. @(posedge CLK) ; // Activate TRDY and DEVSEL drivers, and start // waiting for the IRDY. TRDY_en <= 1; DEVSEL_en <= 1; while (IRDY == 1) @(posedge CLK) ; case (address[11:2]) 9'b000000000: begin dma_go = AD[0]; dma_fifo = AD[1]; dma_count_intr_en = AD[2]; end 9'b000000001: dma_external = AD; 9'b000000010: dma_memory = AD; 9'b000000011: dma_count = AD; default: ; endcase // case(address[11:2]) TRDY_reg <= 1; TRDY_en <= 0; STOP_reg <= 1; STOP_en <= 0; DEVSEL_reg <= 1; DEVSEL_en <= 0; end endtask // do_bar2_write // A simple state machine to request new transactions. always @(posedge CLK) if (REQ == 1 && FRAME_reg == 1 && IRDY_reg==1 && dma_count && dma_go) REQ <= 0; // This implements a DMA bus mastering read from an external // address to local memory. task do_master_read; //write to memory while acting as PCI Master localparam read_cmd = 4'hC; //burst read command begin AD_reg <= dma_external; //source_adr is a register in BAR2 range AD_en <= 1; C_BE_reg <= read_cmd; //reading from a PCI source C_BE_en <= 1; FRAME_reg <= 0; //drive frame active FRAME_en <= 1; parity_bit = ^{dma_external, read_cmd}; @(posedge CLK) ; // advance to turnaround cycle //ignore device select for now FRAME_reg <= 0; //leave frame active FRAME_en <= 1; AD_en <= 0; //stop driving address IRDY_reg <= 0; //turn on IRdy IRDY_en <= 1; C_BE_reg <= 4'd0; //read 4 bytes C_BE_en <= 1; PAR_reg <= parity_bit; //parity of address PAR_en <= 1; if ((IRDY == 0) && (TRDY == 0)) begin write_val = AD; //data to write to memory // Store the next value $pci_memory_poke(memory_fd, dma_memory, write_val, 0); // Linear addressing of memory dma_memory <= dma_memory + 4; dma_count <= dma_count - 4; end // Keep reading so long as the target does not // stop the transaction. Could add a burst count later. while (STOP == 1) @(posedge CLK) begin //stop may be 0 by the time Clk rises PAR_en <= 0; //stop driving parity if (STOP==0) FRAME_reg <= 1; //frame is inactive after stop if ((IRDY == 0) && (TRDY == 0)) begin write_val = AD; // Store the next value $pci_memory_poke(memory_fd, dma_memory, write_val, 0); // Linear addressing. dma_memory <= dma_memory + 4; dma_count <= dma_count - 4; end end // Transaction done. Turn off drivers. @(posedge CLK) begin IRDY_reg <= 1; FRAME_en <= 0; IRDY_en <= 0; C_BE_en <= 0; PAR_en <= 0; end end endtask // do_master_read // This is the main loop that sits here waiting for a bus cycle // to start. Then, I kick in the state machines to complete the // target side of any transaction. always @(posedge CLK) begin if (RESET == 0) do_reset; else if ((FRAME == 1'b1) && (IRDY==1'b1) && (GNT == 0)) begin REQ <= 1; do_master_read; end else if ((FRAME == 1'b1) && pending_flag) pending_flag = 0; else if (pending_flag) ; else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b1010) && (IDSEL == 1'b1)) do_configuration_read; else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b1011) && (IDSEL == 1'b1)) do_configuration_write; else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0110) && selected(AD)) do_memory_read(0); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b1100) && selected(AD)) do_memory_read(0); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b1110) && selected(AD)) do_memory_read(0); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0111) && selected(AD)) do_memory_write(0); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0110) && selected1(AD)) do_memory_read(1); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0111) && selected1(AD)) do_memory_write(1); else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0110) && selected2(AD)) do_bar2_read; else if ((FRAME == 1'b0) && (C_BE[3:0] == 4'b0111) && selected2(AD)) do_bar2_write; else if (FRAME == 1'b0) pending_flag = 1; else begin end end initial begin // Open the memory image. memory_fd = $pci_memory_open(IMAGE, 1 + ~BAR0_MASK); // Get a retry rate from the command line. If there is none // specified, then use the value from the defined parameter. if (0 == $value$plusargs("mem-retry-rate=%d", retry_rate)) retry_rate = RETRY_RATE; if (0 == $value$plusargs("mem-discon-rate=%d", discon_rate)) discon_rate = DISCON_RATE; endendmodule // pci_memory/* * $Log: pci_memory.v,v $ * Revision 1.16 2004/04/30 20:25:40 steve * Fix state machine for DMA reads. * * Revision 1.15 2004/04/30 17:26:27 steve * Add BAR2 and ability to DMA data into memory. * * Revision 1.14 2004/01/20 18:18:12 steve * Make memory device do random disconnects. * * Revision 1.13 2003/11/08 04:00:08 steve * Generate parity for reads from the memory device. * * Revision 1.12 2003/09/16 22:03:56 steve * Document the interface. * * Revision 1.11 2003/06/06 17:54:07 steve * Fix memory write with byte lanes. * * Revision 1.10 2003/05/27 23:59:57 steve * Support explicit byte lane controls on write. * * Revision 1.9 2002/10/16 16:59:14 steve * License updates. * * Revision 1.8 2002/08/22 01:30:06 steve * Add the pcisim memdev device to the library. * * Revision 1.7 2002/08/21 01:54:31 steve * Hold STOP if the FRAME is active during a retry. * * Revision 1.6 2002/08/10 17:21:56 steve * Generate read retries. * * Revision 1.5 2002/08/01 04:08:25 steve * manage pending state of PCI transaction. * * Revision 1.4 2002/06/01 02:21:45 steve * Support MRM command. * * Revision 1.3 2002/05/29 00:46:26 steve * Make the memory image file configurable. * * Revision 1.2 2002/05/12 23:53:14 steve * Add memory write cycles to master and memory. * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -