1 votos

Cómo seleccionar la línea a un demux 1:4 en verliog desde un softprocessor NIOS II

Soy nuevo en verilog. Estoy usando este demux 1:4 como se describe en esta página web (código suministrado).

1:4 Código verilog demux

Mi pregunta es en relación con la línea de selección. Tengo un procesador suave NIOS II en el fpga con una aplicación escrita en c corriendo en él. ¿Cómo podría controlar la línea de selección desde el NIOS? Supongo que escribiría un valor en alguna ubicación pero no estoy seguro de cómo funcionaría precisamente.

Apreciar y consejos de sugerencias.

4voto

Tom Carpenter Puntos 7192

Para que NIOS pueda acceder a los periféricos de la FPGA, es necesario realizar un proceso llamado "Memory Mapping". Esencialmente, esto se reduce a construir el tejido para mapear el periférico a una dirección en el mapa de memoria de NIOS para que pueda acceder a él.

El procesador NIOS utiliza un maestro de datos Avalon-MM para acceder a todos los periféricos, por lo que para conectar las líneas de control de tu demultiplexor, necesitas envolverlas en una interfaz esclava Avalon-MM que luego se conecta al maestro de datos y se le asigna una dirección.

La forma más sencilla de realizar la conexión es utilizar un controlador PIO de Avalon-MM, que es básicamente un núcleo IP que puede utilizarse para conectar entradas o salidas al bus de Avalon-MM. Esto se usa frecuentemente para mapear pines IO externos a NIOS, pero también puede usarse para conexiones internas.

Como alternativa, puede crear directamente una interfaz Avalon-MM en su código demultiplexor. Puede encontrar el especificaciones de la interfaz aquí que le dirá lo que hace cada una de las señales. Para ayudarte, puedes utilizar la siguiente plantilla de Verilog que he creado y utilizo en todos los núcleos IP que hago para usar con NIOS.

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

Esa plantilla maneja la habilitación de bytes, la lectura y la escritura, y también las interrupciones. Puedes eliminar cosas como los manejadores de interrupción para algo tan simple como un demux.

Si estás usando esto con Qsys, necesitarás crear una envoltura TCL para tu núcleo IP. No voy a mostrar una plantilla completa de envoltura, pero a continuación se muestra cómo se añadiría la interfaz Avalon-MM y opcionalmente la interfaz IRQ. Muestro esto porque hay muchas propiedades diferentes para las interfaces Avalon-MM, y las que se muestran a continuación coinciden con la plantilla anterior y se sabe que funcionan.

# 
# 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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X