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