Re: Návrhářem FPGA za 21 dní

Jaroslav Buchta jaroslav.buchta na hascomp.cz
Úterý Říjen 27 06:45:53 CET 2015


V projektu (aspon u Altery) se da michat vsechno, Verilog, CHDL, 
schemata. Vetsina projektu na opencores je ale ve VHDL (aspon ty, co me 
zajimaly) a tim to bylo dano. Kazdopadne aspon okrajove je dobre urcite 
znat oboje, zas tak moc se to nelisi, asi jako pascal a c (doslova, 
verilog asi vychazi z pascalu, same begin, end a hrozne ukecane, VHDL z 
C, jednoduche kratke zapisy ukrutnymi kombinacemi symbolu ;-) )
Ale princip je stejny, zejmena je nutno si zvyknout na to, ze vsechny 
bloky fungujou paralelne a design dobre strukturovat. Nakonec se vesmes 
pouziva par konstrukci typu FSM atp.

Pro ilustraci prikladam muj kod ve VHDL - jednoduchy UART s pevne 
nastavenymi parametry behem syntezy


module cntr8 (
     input clk,
     input sreset,
     output reg ovr,
     input [7:0] cntrtop        // top counter value, div = cntrtop+1/8;
);


reg [7:0] n;

wire ovrw;

assign ovrw = n == cntrtop;

always @(posedge clk) begin
     if (sreset) begin
         ovr <= 1'b0;
         n <= 8'b0;
     end else begin
         ovr <= ovrw;
         n <= ovrw ? 8'd0 : n + 8'd1;
     end
end


endmodule

//////////////////////////////////////////////////////////
module cntrTx (
     input clk,
     input cke,
     input sreset,
     output reg txevt
);

reg [2:0] n;

always @(posedge clk) begin
     if (sreset) begin
         txevt <= 1'b0;
         n <= 3'b0;
     end else begin
         txevt <= (n == 3'd7) && cke;
         n[2:0] <= n[2:0] + (cke ? 3'd1 : 3'd0);
     end
end

endmodule

//////////////////////////////////////////////////////////

module microua_tx (
     input clk,
     input sreset,
     input txevt,
     input [7:0] data,
     input txrq,
     output  txempty,
     output reg txd
);

`define STATE_BITS    2
`define STATE_TX_idle     `STATE_BITS'd0
`define STATE_TX_start     `STATE_BITS'd1
`define STATE_TX_shift     `STATE_BITS'd2
`define STATE_TX_ack     `STATE_BITS'd3


reg [`STATE_BITS-1:0] state;
reg [`STATE_BITS-1:0] nextstate;
reg [8:0] txreg;
wire txdw;

assign txdw = state == `STATE_TX_start ? 1'b0 : (state == 
`STATE_TX_shift ? txreg[0] : 1'b1);
assign txempty = state == `STATE_TX_idle;

always @(posedge clk) begin
     txd <= txdw;
     if (sreset) begin
         state <= `STATE_TX_idle;
         txreg <= 9'd0;
     end else if (txevt) begin
         state <= nextstate;
         if (state == `STATE_TX_shift) txreg[8:0] <= {1'b0, txreg[8:1]};
         else if (nextstate == `STATE_TX_start) txreg[8:0] <= {1'b1, 
data[7:0]};
     end
end

always @(state or txrq or txempty or txreg) begin
     case (state)
         `STATE_TX_idle:
             begin
             if (txrq) nextstate = `STATE_TX_start;
             else nextstate = `STATE_TX_idle;
             end
         `STATE_TX_start:
             begin
             nextstate = `STATE_TX_shift;
             end
         `STATE_TX_shift:
             begin
//            if (txreg[8:1] == 8'd0) nextstate = txrq ? `STATE_TX_ack : 
`STATE_TX_idle;
//            if (txreg[8:1] == 8'd0) nextstate = `STATE_TX_ack;
             if (txreg[8:2] == 7'd0) nextstate = `STATE_TX_idle;
             else nextstate = `STATE_TX_shift;
             end
         `STATE_TX_ack:
             begin
             if (!txrq) nextstate = `STATE_TX_idle;
             else nextstate = `STATE_TX_ack;
             end
         default: nextstate = `STATE_TX_idle;
     endcase

end    //always

endmodule

//////////////////////////////////////////////////////////

module microua_rx (
     input clk,
     input sreset,
     input rxevt8,
     input rxd,
     output reg [7:0] rxreg,
     output reg rxvalid
);

`define STATE_BITS    2
`define STATE_RX_idle     `STATE_BITS'd0
`define STATE_RX_start     `STATE_BITS'd1
`define STATE_RX_shift     `STATE_BITS'd2
`define STATE_RX_stop     `STATE_BITS'd3


reg [`STATE_BITS-1:0] state;
reg [`STATE_BITS-1:0] nextstate;
reg rxdr;
reg [2:0] bittmr;
reg [2:0] bitcntr;

always @(posedge clk) begin
     rxdr <= rxd;
     if (sreset) begin
         rxvalid <= 1'b0;
         rxreg <= 8'd0;
         state <= `STATE_RX_idle;
         rxdr <= 1'b1;
         bitcntr <= 3'd0;
         bittmr <= 3'd0;
     end else if (rxevt8) begin
         state <= nextstate;
         bittmr <= bittmr + 3'd1;
         if (state == `STATE_RX_idle && !rxdr) begin
             bitcntr <= 3'd0;
             bittmr <= 3'd5;        // precompensation processing delay
             rxvalid <= 1'b0;
         end if (state == `STATE_RX_shift && bittmr == 0) begin
             rxreg[7:0] <= {rxdr, rxreg[7:1]};
             bitcntr <= bitcntr + 3'd1;
         end if (state == `STATE_RX_stop && bittmr == 0 && rxdr) begin
             rxvalid <= 1'b1;
         end
     end
end

always @(state or rxdr or bittmr or bitcntr) begin
     case (state)
         `STATE_RX_idle:
             begin
             if (!rxdr) nextstate = `STATE_RX_start;
             else nextstate = `STATE_RX_idle;
             end
         `STATE_RX_start:
             begin
             if (bittmr == 0) nextstate = !rxdr ? `STATE_RX_shift : 
`STATE_RX_idle;
             else nextstate = `STATE_RX_start;
             end
         `STATE_RX_shift:
             begin
             if (bitcntr == 7 && bittmr == 0) nextstate = `STATE_RX_stop;
             else nextstate = `STATE_RX_shift;
             end
         `STATE_RX_stop:
             begin
             if (bittmr == 0) nextstate = `STATE_RX_idle;
             else nextstate = `STATE_RX_stop;
             end
         default: nextstate = `STATE_RX_idle;
     endcase

end    //always

endmodule

------------------------------- a propojeni vyse uvedenych modulu:

module MicrouartTop (
         input clk_main,            // external main clock signal, 50 MHz
         input sync_reset,            // reset signal, sync with clk_main
         input sig_rxd,                // RxD interface signal
         output sig_txd,            // TxD interface signal
         input [7:0] tx_data,        // tx data to send
         input tx_dstb,                // tx data strobe, must be active 
to reset tx_empty
         output tx_empty,            // tx empty and ready to next data
         output [7:0] rx_data,    // rx data received
         output rx_dvalid            // rx data valid signal (posedge 
active)
);

     wire ovr;
     wire txevt;

     cntr8 baudBase (
         .clk (clk_main),
         .sreset (sync_reset),
         .ovr (ovr),
         .cntrtop(8'd54-8'd1)            // 50000000/115200/8 = 54,25
     );


     cntrTx txBase(
         .clk (clk_main),
         .cke (ovr),
         .sreset (sync_reset),
         .txevt (txevt)
     );


     microua_tx tx_inst (
         .clk (clk_main),
         .sreset (sync_reset),
         .txevt (txevt),
         .data (tx_data),
         .txrq (tx_dstb),
         .txempty (tx_empty),
         .txd (sig_txd)
     );

     microua_rx rx_inst (
         .clk (clk_main),
         .sreset (sync_reset),
         .rxevt8 (ovr),
         .rxd (sig_rxd),
         .rxreg (rx_data[7:0]),
         .rxvalid (rx_dvalid)
     );

endmodule





Další informace o konferenci Hw-list