verilog 层次化设计的简单问题 -- 如何调用底层模块

假设三个模块module top_m, bottom1_m, bottom2_m  分别存在于三个文件top.v, bottom1.v, bottom2.v  请问我要在top_m 模块内调用两个底层模块bottom1_m, bottom2_m  如何实现,如何链接?  实现后是否可综合?
请教各位大侠了!……

 

在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

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值