在Verilog中,调用底层模块的语法结构为:
底层模块名 实例名 参数定义
比如在top_m里,如果已经全部源文件加到了同一个工程里,那么可以直接
bottom1_m bottom1_m(A,B,C)
注意 A,B,C这些参数的顺序,要和底层定义的是一致的。名字可以不一致。
如果没有加到同一个工程,可以使用
'include "bottom1.v"
可不可以综合,这个得看你代码怎么写的,和层次无关。
module uart_top(clk, nreset, rec, send, data);
input clk;
input nreset;
input rec;
output send;
parameter len = 16;
output [len:0]data;
uart_rec rec1( //底层模块1
.rec(rec),
.clk(clk),
.nreset(nreset),
.data(data)
);
uart_send send1(//底层模块2
.data(data),
.clk(clk),
.nreset(nreset),
.send(send)
);
endmodule
你的子模块 uart_rec和uart_send模块我不知道具体的实现,只能告诉你:
第一,模块实例化以后,相当于一个实际的电路,是物理上存在的实体,并非函数。所以,不存在always调用这一说。如果你的子模块设计得当,那么,只要输入的信号满足你的条件,模块就有相应输出;
第二,你要看子模块的相关文档,如果是自己写的,要搞清楚UART时序;
第三,不要把接收寄存器(data)和发送寄存器用同一个,而且,17位的寄存器有点怪;
第四,你可以在代码里用always来完成判断什么时候该去从模块中读取数据(或者写入),什么时候复位等等。always后面的条件,可能是9个时钟(看你的UART设置),又或者是data被赋值或清空,这个要看子模块如何设计的;
第五,网络上有verilog或者VHDL实现UART的代码,google一下很容易找到,可以用来做参考,学习的效果应该比在这里问问题要强一点,也要连续一些。 ///////////////////////////////////////////////////////////////////////////////////////////
ADI的代码: ////////////////////////////////////////////////////////////////////////////////
// Company: Analog Devices Inc.
// Engineer: MH
//
// Design Name: AD9239 ADI Link
// Project Name: AD9239 ADI Link
// Target Devices: Altera Stratix II GX
// Tool versions: Quartus II v8.0 sp1
//
// Description: Top module.
//
// Dependencies: None
//
// Revision:
// 1.00 - 10/27/08 - Initial
//
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module ad9239_gxb_adi (chan_a, chan_b, chan_c, chan_d,
pgm0, pgm1, pgm2, pgm3, pwr_dwn,
core_clk, mr, wen, ren_a, full,
rclk, cs_fpga, sclk, sdi, spi_rst,
data, data_rdy, sdo,
led6, led4, led1, led2,
led3, led5, led7); input chan_a, chan_b, chan_c, chan_d;
input mr, wen, ren_a, rclk, core_clk;
input cs_fpga, sclk, sdi; output pgm0, pgm1, pgm2, pgm3, sdo;
output data_rdy, pwr_dwn, spi_rst;
output led6, led4, led1, led2;
output led3, led5, led7, full;
output [15:0] data; wire freqlocked;
wire analog_rst, digital_rst;
wire frame, par_dclk;
wire [1:0] chan_sel;
wire [1:0] dut_ctrl;
wire [2:0] scram_sel;
wire [3:0] serial_data;
wire [63:0] par_dat, descram_dat; // use LED's to indicate configuration
assign led1 = ~chan_sel[1];
assign led2 = ~chan_sel[0];
assign led3 = ~scram_sel[2];
assign led4 = ~scram_sel[1];
assign led5 = ~scram_sel[0];
assign led6 = ~dut_ctrl[1];
assign led7 = ~dut_ctrl[0]; assign serial_data = {chan_a, chan_b, chan_c, chan_d};
assign pgm3 = frame;
assign pgm2 = frame;
assign pgm1 = frame;
assign pgm0 = frame; assign spi_rst = dut_ctrl[1];
assign pwr_dwn = dut_ctrl[0]; // apply analog and digital reset
reset_cntrl U1 (.clk(core_clk),
.gxb_rst(~mr),
.freq_lock(freqlocked),
.analog_rst(analog_rst),
.digital_rst(digital_rst)); // use SPI for channel select
spi_rw U2 (.I_sclk(sclk),
._I_csb(cs_fpga),
.I_sdi(sdi),
.O_sdo(sdo),
.spi_reg3(chan_sel),
.spi_reg4(scram_sel),
.spi_reg5(dut_ctrl)); // create 64-bit parallel packet
packet U3 (.digital_rst(digital_rst),
.analog_rst(analog_rst),
.core_clk(core_clk),
.serial_data(serial_data),
.freqlocked(freqlocked),
.frame(frame),
.chan_sel(chan_sel),
.par_dat(par_dat),
.par_dclk(par_dclk)); // descramble data
descramble U4 (.scram_sel(scram_sel[2:0]),
.par_dclk(par_dclk),
.par_dat64(par_dat),
.descram64(descram_dat)); // write to and read from FIFO
fifo16 U5 (.reset(~mr),
.data_in(descram_dat),
.mode(frame),
.wen(~wen),
.full(full),
.par_dclk(par_dclk),
.frame(frame),
.ren(~ren_a),
.rclk(rclk),
.data_rdy(data_rdy),
.dout(data)); endmodule
////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Company: Analog Devices Inc.
// Engineer: MH
//
// Design Name: AD9239 ADI Link
// Project Name: AD9239 ADI Link
// Target Devices: Altera Stratix II GX
// Tool versions: Quartus II v8.0 sp1
//
// Description: reset_cntrl module.
//
// Dependencies: ff1.v, counter12.v
//
// Revision:
// 1.00 - 10/27/08 - Initial
//
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module reset_cntrl(clk, gxb_rst, freq_lock,
analog_rst, digital_rst); input clk, gxb_rst;
input freq_lock; output analog_rst;
output digital_rst; wire [11:0] cnt_a, cnt_d; ff1 F1 (.aclr(gxb_rst),
.clock(clk),
.data(1'b1),
.sclr(&cnt_a),
.sset(1'b0),
.q(analog_rst)); ff1 F2 (.aclr(gxb_rst),
.clock(clk),
.data(1'b1),
.sclr(&cnt_d),
.sset(1'b0),
.q(digital_rst)); counter12 C1 (.aclr(gxb_rst),
.clk_en(~&cnt_a),
.clock(clk),
.q(cnt_a)); counter12 C2 (.aclr(gxb_rst),
.clk_en(freq_lock & {~&cnt_d}),
.clock(clk),
.q(cnt_d)); endmodule
/////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Company: Analog Devices Inc.
// Engineer: MH
//
// Design Name: AD9239 ADI Link
// Project Name: AD9239 ADI Link
// Target Devices: Altera Stratix II GX
// Tool versions: Quartus II v8.0 sp1
//
// Description: spi_control
//
// Dependencies: none
//
// Revision:
// 1.00 - 10/27/08 - Initial
//
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module spi_control
(
//
// ------- Inputs -------
//
input I_sclk, // Serial data clock
input _I_csb, // Active low chip select
input I_sdi, // Serial data input
//
// ------- Outputs -------
//
output reg O_rw, // Read/write indicator (1 = read, 0 = write)
output reg O_astrobe, // Address strobe to enable address decoding
output reg O_dstrobe, // Data strobe to enable data decoding and encoding
output reg O_sync // Sync pulse to enable reads or writes from memory
); //Use one-hot state encoding for FPGA.
localparam [9:0] S_RESET = 10'b00_0000_0001, //Reset state.
S_RINST = 10'b00_0000_0010, //Read instruction state.
S_RADDR = 10'b00_0000_0100, //Read address state.
S_RSYNC = 10'b00_0000_1000, //Read sync state.
S_RDATA = 10'b00_0001_0000, //Read data state.
S_WINST = 10'b00_0010_0000, //Write instruction state.
S_WADDR = 10'b00_0100_0000, //Write address state.
S_WDATA = 10'b00_1000_0000, //Write data state.
S_WSYNC = 10'b01_0000_0000, //Write sync state.
S_WPOST = 10'b10_0000_0000; //Post write sync state. reg [9:0] state, next; // State registers
reg [4:0] sclk_count; // Serial data clock count // State assignment
always @(posedge I_sclk or posedge _I_csb)
if (_I_csb) state <= S_RESET;
else state <= next; // Keep track of I_sclk cycle count.
always @(posedge I_sclk or posedge _I_csb)
if (_I_csb) sclk_count <= 5'h0;
else sclk_count <= (sclk_count < 5'h17) ? sclk_count + 5'h01 : 5'h10; // Register outputs on I_sclk edge
always @(posedge I_sclk or posedge _I_csb) begin
if (_I_csb) begin
O_rw <= 1'b1;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
else begin
case (next)
S_RESET: begin
O_rw <= 1'b1;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
S_RINST: begin
O_rw <= 1'b1;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
S_RADDR: begin
O_rw <= 1'b1;
O_astrobe <= 1'b1;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
S_RSYNC: begin
O_rw <= 1'b1;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b1;
O_sync <= 1'b1;
end
S_RDATA: begin
O_rw <= 1'b1;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b1;
O_sync <= 1'b0;
end
S_WINST: begin
O_rw <= 1'b0;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
S_WADDR: begin
O_rw <= 1'b0;
O_astrobe <= 1'b1;
O_dstrobe <= 1'b0;
O_sync <= 1'b0;
end
S_WDATA: begin
O_rw <= 1'b0;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b1;
O_sync <= 1'b0;
end
S_WSYNC: begin
O_rw <= 1'b0;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b1;
O_sync <= 1'b1;
end
S_WPOST: begin
O_rw <= 1'b0;
O_astrobe <= 1'b0;
O_dstrobe <= 1'b1;
O_sync <= 1'b0;
end
endcase
end
end // State machine:
// Monitor SCLK cycles to determine when to change states.
always @(state or I_sdi or sclk_count) begin
case (state)
S_RESET: begin
// Check first bit for read/write instruction indicator.
if (I_sdi == 1'b1)
next = S_RINST;
else
next = S_WINST;
end
S_RINST: begin
if (sclk_count < 5'h02)
next = S_RINST;
else
next = S_RADDR;
end
S_RADDR: begin
if (sclk_count < 5'h0F)
next = S_RADDR;
else
next = S_RSYNC;
end
S_RSYNC: next = S_RDATA;
S_RDATA: begin
if (sclk_count < 5'h17)
next = S_RDATA;
else
next = S_RSYNC;
end
S_WINST: begin
if (sclk_count < 5'h02)
next = S_WINST;
else
next = S_WADDR;
end
S_WADDR: begin
if (sclk_count < 5'h0F)
next = S_WADDR;
else
next = S_WDATA;
end
S_WDATA: begin
if (sclk_count < 5'h16)
next = S_WDATA;
else
next = S_WSYNC;
end
S_WSYNC: next = S_WPOST;
S_WPOST: next = S_WDATA;
endcase
end endmodule
|