Jump to content

How to connect two signals directly?


Lubomir Bogdanov

Recommended Posts

Hello everyone,
I was wondering if it is possible to connect two signals from different SC_MODULEs together without ports?

The reason I want to try this is my flash_memory model - I want it to receive an address
on a rising edge of its clock signal and produce the resulting word on the falling edge of
that same clock.

However, if I use ports, I get additional delays because the ports are buffered (I guess).
Here is a highly generalized model of my system with ports:

 

SC_MODULE(micrcontroller){
	sc_in_clk clock {"mcu_clock"};
	sc_signal<bool, SC_MANY_WRITERS> read_write {"mcu_read_write"}; 
	sc_signal<bool, SC_MANY_WRITERS> interrupt_request {"mcu_interrupt_request"};
	sc_signal<sc_lv<16>, SC_MANY_WRITERS> instr_data_bus {"mcu_instr_data_bus"};
	sc_signal<sc_lv<20>, SC_MANY_WRITERS> address_bus {"mcu_address_bus"};

	microprocessor *cpu;
	flash_memory *flash;
	sram_memory *sram;

	micrcontroller(::sc_core::sc_module_name);
	~micrcontroller();
};

SC_MODULE(microprocessor){
	sc_in_clk clock {"upu_clock"};
	sc_out<bool> read_write {"upu_read_write"}; 
	sc_in<bool> interrupt_request {"upu_interrupt_request"}; 
	sc_inout<sc_lv<16>> instr_data_bus {"upu_instr_data_bus"};
	sc_out<sc_lv<20>> address_bus {"upu_address_bus"};

	void fetch();
	void decode();
	void execute();
	void interrupt();

	SC_CTOR(microprocessor){
		SC_CTHREAD(fetch, clock.value_changed());
		SC_CTHREAD(decode, clock.value_changed());
		SC_CTHREAD(execute, clock.value_changed());
		SC_CTHREAD(interrupt, clock.value_changed());
	}

	~microprocessor();
};

SC_MODULE(flash_memory){
	sc_in_clk clock {"flash_memory_clock"} ;
	sc_in<bool> read_write {"flash_memory_read_write"}; 
	sc_inout<sc_lv<16>> data_bus {"flash_memory_data_bus"};
	sc_in<sc_lv<20>> address_bus {"flash_memory_address_bus"};

	void flash_loop();

	SC_CTOR(flash_memory){
		SC_CTHREAD(flash_loop, clock.value_changed());
	}

	~flash_memory();
};

SC_MODULE(sram_memory){
	sc_in_clk clock {"sram_memory_clock"} ;
	sc_in<bool> read_write {"sram_memory_read_write"}; 
	sc_inout<sc_lv<16>> data_bus {"sram_memory_data_bus"};
	sc_in<sc_lv<20>> address_bus {"sram_memory_address_bus"};

	void sram_loop();

	SC_CTOR(sram_memory){
		SC_CTHREAD(sram_loop, clock.value_changed());
	}

	~sram_memory();
};

 

and in the microcontroller's (top-level module) constructor I connect them with signals like this:

microcontroller::microcontroller(::sc_core::sc_module_name){
	read_write = 1;
	interrupt_request = 0;
	instr_data_bus = 0x00;
	address_bus = 0x00;

	cpu = new microprocessor("cpu");
	cpu->address_bus(address_bus);
	cpu->instr_data_bus(instr_data_bus);
	cpu->clock(clock);
	cpu->read_write(read_write);
	cpu->interrupt_request(interrupt_request);

	flash = new flash_memory("flash");
	flash->address_bus(address_bus);
	flash->data_bus(instr_data_bus);
	flash->clock(clock);
	flash->read_write(read_write);

	sram = new sram_memory("sram");
	sram->address_bus(address_bus);
	sram->data_bus(instr_data_bus);
	sram->clock(clock);
	sram->read_write(read_write);
}

 

This yields:

============== 1 ==============
(microprocessor) r0: 004402 address_bus: 004400 instr_data_bus: 00000
r: mem[004400] = 0
============== 0 ==============
(microprocessor) r0: 004402 address_bus: 004400 instr_data_bus: 00000
r: mem[004400] = 0
============== 1 ==============
(microprocessor) r0: 004404 address_bus: 004402 instr_data_bus: 0e0f2
r: mem[004402] = e0f2


which is half-a-period longer than I what I want.

I've noticed that I can do this:

 

SC_MODULE(micrcontroller){
	sc_in_clk clock {"mcu_clock"};
	sc_signal<bool, SC_MANY_WRITERS> read_write {"mcu_read_write"}; 
	sc_signal<bool, SC_MANY_WRITERS> interrupt_request {"mcu_interrupt_request"};
	sc_signal<sc_lv<16>, SC_MANY_WRITERS> instr_data_bus {"mcu_instr_data_bus"};
	sc_signal<sc_lv<20>, SC_MANY_WRITERS> address_bus {"mcu_address_bus"};

	void cpu();
	void flash();
	void sram();

	SC_CTOR(micrcontroller){
		SC_CTHREAD(cpu, clock.value_changed());
		SC_CTHREAD(flash, clock.value_changed());
		SC_CTHREAD(sram, clock.value_changed());
	}
	~micrcontroller();
};

 

then I would only use signals without ports and there is no delay in the communication. However, this would break my
module separation and I fear that at some point, as the system gets more and more complex, I might get into some nasty
spaghetti code.

Regards,
L. B.

Link to comment
Share on other sites

Ports are not buffered. Ports are effectively pointers to channels. You cannot connect ports to ports unless they are hierarchical wrt to each other. You can connect ports to sc_exports. 
 

None of this will make much sense until you understand the fundamental nature and purpose of channels, interfaces and ports. SystemC is C++. Forget any ideas you have from Verilog or VHDL (although there are parallel ideas).

When you write to a port, you are effectively writing to a channel pointed to or referenced by the port. And when you write to a channel, you are calling a subroutine located inside that channel class.

sc_signal is a very primitive channel.
 

A channel is a class implementing an interface (abstract class). The port is bound to the interface and accesses the methods through polymorphism. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...