Cómo seleccionar una línea a un demux 1: 4 en un verliog desde un procesador de software NIOS II

1

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

1: 4 Demux verilog code

Mi pregunta es en relación con la línea de selección. Tengo un procesador de software NIOS II en el fpga con una aplicación escrita en c que se ejecuta en él. ¿Cómo controlaría la línea de selección desde el NIOS? Supongo que escribiría un valor en algún lugar, pero no estoy seguro de cómo funcionaría con precisión.

Aprecio y consejos de sugerencias.

    
pregunta artic sol

1 respuesta

3

Para que NIOS acceda a los periféricos en el FPGA, debe realizar un proceso llamado "Asignación de memoria". Esencialmente, esto se reduce a la creación de tejido para asignar el periférico a una dirección en el mapa de memoria 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 tanto, para conectar las líneas de control de su demultiplexor, debe incluirlos en una interfaz esclava Avalon-MM que luego se conecta al maestro de datos. y asignó una dirección.

La forma más sencilla de hacer la conexión es usar un controlador Palon Avalon-MM que es básicamente un núcleo IP que se puede usar para conectar entradas o salidas al bus Avalon-MM. Esto se usa con frecuencia para asignar pines IO externos a NIOS, pero también se puede usar para conexiones internas.

Alternativamente, puede crear directamente una interfaz Avalon-MM en su código de demultiplexador. Puede encontrar las especificaciones de interfaz aquí que Te dirá lo que hace cada una de las señales. Para ayudarlo, puede usar la siguiente plantilla de Verilog que creé y uso en todos los núcleos de IP que utilizo para 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 las habilitaciones de bytes, lee y escribe, y también interrumpe. Puedes quitar cosas como los controladores de interrupciones para algo tan simple como un demux.

Si está utilizando esto con Qsys, deberá crear un contenedor TCL para su núcleo IP. No mostraré una plantilla de envoltura completa, pero a continuación se muestra cómo agregaría la interfaz Avalon-MM y, opcionalmente, la interfaz IRQ. Estoy mostrando 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
    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas