So wählen Sie eine Leitung zu einem 1:4-Demux in Verliog von einem NIOS II-Softprozessor aus

Ich bin neu bei verilog. Ich verwende diesen 1:4-Demux wie auf dieser Webseite beschrieben (Code bereitgestellt).

1:4 Demux-Verilog-Code

Meine Frage bezieht sich auf die Auswahlzeile. Ich habe einen Softprozessor NIOS II auf dem FPGA mit einer in c geschriebenen Anwendung, die darauf läuft. Wie würde ich die ausgewählte Leitung vom NIOS steuern? Ich nehme an, dass Sie einen Wert an einen Ort schreiben würden, aber ich bin mir nicht sicher, wie es genau funktionieren würde.

Schätzen und Tipps von Vorschlägen.

Antworten (1)

Damit NIOS auf Peripheriegeräte im FPGA zugreifen kann, müssen Sie einen Prozess namens "Memory Mapping" durchführen. Im Wesentlichen läuft dies darauf hinaus, Fabric zu bauen, um das Peripheriegerät einer Adresse in der NIOS-Speicherkarte zuzuordnen, damit Sie darauf zugreifen können.

Der NIOS-Prozessor verwendet einen Avalon-MM-Datenmaster für den Zugriff auf alle Peripheriegeräte. Um die Steuerleitungen Ihres Demultiplexers anzuschließen, müssen Sie sie also in eine Avalon-MM-Slave-Schnittstelle einwickeln, die dann mit dem Datenmaster verbunden und zugewiesen wird Adresse.

Der einfachste Weg, die Verbindung herzustellen, ist die Verwendung eines Avalon-MM PIO-Controllers, der im Grunde ein IP-Core ist, der verwendet werden kann, um Ein- oder Ausgänge mit dem Avalon-MM-Bus zu verbinden. Dies wird häufig zum Zuordnen externer IO-Pins zu NIOS verwendet, kann aber auch für interne Verbindungen verwendet werden.

Alternativ können Sie direkt eine Avalon-MM-Schnittstelle in Ihrem Demultiplexer-Code erstellen. Hier finden Sie die Schnittstellenspezifikationen , aus denen hervorgeht, was die einzelnen Signale tun. Um Ihnen zu helfen, können Sie die folgende Verilog-Vorlage verwenden, die ich erstellt und in allen IP-Kernen verwendet habe, die ich für die Verwendung mit NIOS herstelle.

module avalon_mm_template_hw (
    //Clock and Reset inputs
    input             clock,
    input             reset,

    //CSR Interface
    input      [ 1:0] csr_address,
    input             csr_write,
    input      [31:0] csr_writedata,
    input             csr_read,
    output reg [31:0] csr_readdata,
    input      [ 3:0] csr_byteenable,

    //Interrupt Interface
    output            csr_irq
);

//
// CSR Interface
//

localparam IRQS = 2; //Number of interrupt sources
reg  [         IRQS-1:0] irqEnable;
wire [         IRQS-1:0] irqSources;
reg  [         IRQS-1:0] irqEdgeDetect;
reg  [         IRQS-1:0] irqAsserted;

assign csr_irq    = |(irqAsserted & irqEnable);  //IRQ line goes high when any unmasked IRQ line is asserted.
assign irqSources = { "<irqSourceName>", "<anotherIrqSourceName>" }; //IRQ sources - IRQ will be triggered at rising edge.

wire [31:0] dataFromMaster;
wire [31:0] dataToMaster [3:0];
wire [31:0] bitenable;

//Convert byte enable signal into bit enable (basically each group of 8 bits is assigned to the value of the corresponding byte enable.
assign bitenable = {{8{csr_byteenable[3]}},{8{csr_byteenable[2]}},{8{csr_byteenable[1]}},{8{csr_byteenable[0]}}}; 
assign dataFromMaster = csr_writedata & bitenable;

//Set up the Read Data Map for the CSR.
//                       |31                           24|23  16|15  8|7  0|
assign dataToMaster[0] = {                                  "<signalName>" }; //Input signals are mapped to correct bits
assign dataToMaster[1] = {                                  "<signalName>" }; //at the correct addresses here.
assign dataToMaster[2] = {                                  "<signalName>" };
assign dataToMaster[3] = { {(8 - IRQS){1'b0}} irqAsserted,           24'b0 };

always @ (posedge clock) begin
    if (csr_read) begin
        csr_readdata <= dataToMaster[csr_address]; //when CSR read is asserted, clock the correct address of the CSR map on to the outputs.
    end
end

//Generate the IRQ edge detection logic.
genvar i;
generate for (i = 0; i < IRQS; i=i+1) begin : irq_loop
    always @ (posedge clock or posedge reset) begin
        if (reset) begin
            irqAsserted[i]   <= 1'b0;
            irqEdgeDetect[i] <= 1'b0;
        end else begin
            if (csr_write && (csr_address == 2'd3) && dataFromMaster[i+24]) begin 
                //writing a 1 to the corresponding bit in address 3 clears IRQ flag.
                irqAsserted[i] <= 1'b0;
            end else if (irqSources[i] & ~irqEdgeDetect[i]) begin //At rising edge of IRQ Source, assert its flag.
                irqAsserted[i] <= 1'b1;
            end
            irqEdgeDetect[i] <= irqSources[i];
        end
    end
end endgenerate

//CSR Write logic
always @ (posedge clock or posedge reset) begin
    if (reset) begin
        irqEnable       <= {(IRQS){1'b0}};
        "<signalName>"  <= {("<signalWidth>"){1'b0}};
    end else if (csr_write) begin //When a write is issued, update the registers at the corresponding address.
        if (csr_address == 2'd0) begin
            "<signalName>" <= ("<signalName>" & ~bitenable[0+:"<signalWidth>"]) | dataFromMaster[0+:"<signalWidth>"];
        end
        if (csr_address == 2'd3) begin
            //Doesn't have to be at this address, just an example
            irqEnable   <= (  irqEnable & ~bitenable[8+:IRQS]) | dataFromMaster[8+:IRQS]; //IRQ enable mask
        end
        //And so on for all write addresses
    end
end



//... End CSR ...


endmodule

Diese Vorlage handhabt Byte-Freigaben, -Lesen und -Schreiben sowie Interrupts. Sie können Dinge wie Interrupt-Handler für etwas so Einfaches wie einen Demux entfernen.

Wenn Sie dies mit Qsys verwenden, müssen Sie einen TCL-Wrapper für Ihren IP-Core erstellen. Ich werde keine vollständige Wrapper-Vorlage zeigen, aber unten ist, wie Sie die Avalon-MM-Schnittstelle und optional die IRQ-Schnittstelle hinzufügen würden. Ich zeige dies, weil es viele verschiedene Eigenschaften für Avalon-MM-Schnittstellen gibt und die unten gezeigten mit der obigen Vorlage übereinstimmen und bekanntermaßen funktionieren.

# 
# connection point csr
# 
add_interface csr avalon end
set_interface_property csr addressUnits WORDS
set_interface_property csr associatedClock clock
set_interface_property csr associatedReset reset
set_interface_property csr bitsPerSymbol 8
set_interface_property csr burstOnBurstBoundariesOnly false
set_interface_property csr burstcountUnits WORDS
set_interface_property csr explicitAddressSpan 0
set_interface_property csr holdTime 0
set_interface_property csr linewrapBursts false
set_interface_property csr maximumPendingReadTransactions 0
set_interface_property csr maximumPendingWriteTransactions 0
set_interface_property csr readLatency 1
set_interface_property csr readWaitStates 0
set_interface_property csr readWaitTime 0
set_interface_property csr setupTime 0
set_interface_property csr timingUnits Cycles
set_interface_property csr writeWaitTime 0
set_interface_property csr ENABLED true

add_interface_port csr csr_address address Input 2
add_interface_port csr csr_readdata readdata Output 32
add_interface_port csr csr_writedata writedata Input 32
add_interface_port csr csr_write write Input 1
add_interface_port csr csr_read read Input 1
add_interface_port csr csr_byteenable byteenable Input 4
set_interface_assignment csr embeddedsw.configuration.isFlash 0
set_interface_assignment csr embeddedsw.configuration.isMemoryDevice 0
set_interface_assignment csr embeddedsw.configuration.isNonVolatileStorage 0
set_interface_assignment csr embeddedsw.configuration.isPrintableDevice 0

# 
# connection point csr_irq
# 

add_interface csr_irq interrupt sender
set_interface_property csr_irq associatedAddressablePoint csr
set_interface_property csr_irq associatedClock clock
set_interface_property csr_irq associatedReset reset
set_interface_property csr_irq irqScheme NONE

add_interface_port csr_irq csr_irq irq Output 1
Hallo @Tom Carpenter, vielen Dank für deine ausführliche und hilfreiche Antwort. Ich werde versuchen deinen Vorschlag umzusetzen.